<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>llops blog &#187; Artículos</title>
	<atom:link href="http://llops.com/blog/category/articulos/feed/" rel="self" type="application/rss+xml" />
	<link>http://llops.com/blog</link>
	<description>Blog de programación creativa mantenido por llops. Experimentos y artículos entorno a la plataforma flash y as3.</description>
	<lastBuildDate>Fri, 07 Oct 2011 22:22:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Medidas y resoluciones en Flash</title>
		<link>http://llops.com/blog/2009/09/19/medidas-y-resoluciones-en-flash/</link>
		<comments>http://llops.com/blog/2009/09/19/medidas-y-resoluciones-en-flash/#comments</comments>
		<pubDate>Sat, 19 Sep 2009 16:50:20 +0000</pubDate>
		<dc:creator>llops</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[diseño líquido]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[medidas]]></category>
		<category><![CDATA[resolución mínima]]></category>
		<category><![CDATA[resoluciones]]></category>
		<category><![CDATA[scroll]]></category>
		<category><![CDATA[swffit]]></category>
		<category><![CDATA[utils]]></category>

		<guid isPermaLink="false">http://llops.com/blog/?p=131</guid>
		<description><![CDATA[Está en la naturaleza del html que su contenido se ajuste a las medidas del navegador, reposicionando el contenido automáticamente y generando scrolls cuando éste supera unas medidas mínimas. Un swf, por el contrario, simplemente es un objeto embebido en un html con unas dimensiones y una posición fija por defecto. Cualquier comportamiento extra que [...]]]></description>
			<content:encoded><![CDATA[<p>Está en la naturaleza del html que su contenido se ajuste a las medidas del navegador, reposicionando el contenido automáticamente y generando scrolls cuando éste supera unas medidas mínimas. Un swf, por el contrario, simplemente es un objeto embebido en un html con unas dimensiones y una posición fija por defecto. Cualquier comportamiento extra que deba adoptar un swf dentro del navegador para visualizarse correctamente recae sobre el programador.</p>
<p>Desde el punto de vista de Flex, esto no supone un gran problema ya que por defecto el framework está dotado de un sistema que permite crear una interfaz líquida con muy poco esfuerzo. Pero si hablamos de Flash, no existe un mecanismo que nos ayude a adaptar nuestra película a cualquier resolución.</p>
<p><span id="more-131"></span></p>
<h4>Diseño líquido vs diseño estático</h4>
<p>Mientras que en html se han acuñado muchos términos a la hora de hablar de los diseños (fijo, estático, flexible, líquido, fluido, elástico…), en flash, básicamente, podemos hablar que un site tiene un diseño líquido o estático.</p>
<p>En un diseño líquido el contenido se posiciona en función del tamaño del navegador. El programador debe decidir elemento por elemento si está anclado, si se ha de reescalar, reposicionar, etc. Y dependiendo de la complejidad del site puede ser un trabajo realmente complejo y tedioso.</p>
<p>Por contra, en el diseño fijo le damos un alto y un ancho a nuestra película y todos los elementos quedan ubicados de manera absoluta. Aunque a nivel de diseño y de programación es comodísimo, el problema estriba en que si alguien accede con una resolución mucho mayor verá la página pequeña desperdiciando mucho espacio, y si es menor se generarán barras de scroll que pueden dificultar la experiencia y la navegación.</p>
<p>Se elija uno u otro, siempre hay que decidir qué <strong>resolución mínima</strong> tendrá nuestra web.</p>
<h4>Resolución mínima</h4>
<p>Una de las primeras tareas que deberíamos hacer cuando empezamos un proyecto es decidir qué resolución mínima usaremos, o dicho de otra manera, a partir de que <strong>resolución de pantalla</strong> nuestros usuarios verán el contenido sin problemas. Hace unos años el estándard era 800&#215;600, encontrándose ahora normalmente en 1024&#215;768.</p>
<p>Aún tratándose de una web líquida, es recomendable fijar un mínimo para que los elementos no queden apelotonados cuando el navegador se reduce demasiado.</p>
<h4>El problema</h4>
<p>De manera más o menos consciente, cualquier site está pensado para trabajar con una resolución mínima, pero el gran problema es que mucha gente <strong>se olvida de las resoluciones inferiores</strong>. La razón de escoger medidas es ofrecer garantías de que una web será visualizada correctamente en la mayoría de los casos, pero en aquellos que no se pueda, <strong>todo el contenido</strong> debe seguir siendo igualmente <strong>accesible</strong>.</p>
<blockquote><p><strong>Nota:</strong> en este contexto, accesible hace referencia a que el contenido se puede ver/clicar, no hablo de accesibilidad web.</p></blockquote>
<p>Y este problema no está asociado únicamente a nuevos programadores o gente inexperta. Sin ir más lejos, aquí hay dos ejemplos sacados del <a title="The Favourite Website Award" href="http://www.thefwa.com/" target="_blank">FWA</a> (ambos recientes, nada de buscar en el 2006):</p>
<ul>
<li><a href="http://www.energylab.tv">http://www.energylab.tv</a></li>
<li><a href="http://www.harrypottertweet.com">http://www.harrypottertweet.com</a></li>
</ul>
<p>En el primero de ellos reescalan el contenido, pero si tu resolución es de 800x600px se corta y no se puede acceder al menú inferior de opciones. En el segundo, con la misma resolución, no se puede acceder al botón para detener el audio.</p>
<p>En ambos casos, los programadores decidieron que la resolución mínima de sus webs sería de 1024&#215;768, pero han descartado al resto. Detectando que la medida del navegador era inferior y añadiendo un scroll vertical posibilitarían que todo el mundo pudiera acceder a todos los elementos.</p>
<h4>Un ejemplo de lo impredecible de la web</h4>
<p>Muchas veces nos creemos con derecho a descartar a x usuarios pensando que son una minoría, como cuando empezamos a dejar de lado a los usuarios con monitores de 800&#215;600, pensando que una altura de 600px nunca más se daría.</p>
<p>Pues bien, un tiempo después empieza a proliferar un pequeño ordenador llamado <em>netbook</em>, cuya resolución estándard es de 1024&#215;600. En los últimos 3 años, mientras que la venta de ordenadores cae de manera incremental, el crecimiento de los netbooks lleva un ritmo que nadie era capaz de predecir.</p>
<p>Yo, en mi netbook, ¿por qué no puedo navegar la web de energylab? ¿o porqué no puedo detener el volumen en la de harrypotter?</p>
<blockquote><p>No caigamos en la demagogia fácil de las minorías, en la que alguien pudiera decir &#8220;Pues no uses Flash entonces, que hay unos cuantos que no tienen el plugin&#8221;. Cualquiera, en función de objetivos, es libre de escoger la tecnología que mejor se ciñe a su propósito, así como la resolución. Si un artista considera que la resolución mínima para ver bien sus pinturas ha de ser de 1920&#215;1050, perfecto. Pero si descarta las inferiores muchos sólo verán parte de la pintura, mientras que si habilita el scroll dará la posibilidad a todo el mundo de verla íntegra.</p></blockquote>
<h4>Eligiendo una resolución</h4>
<p>Un error frecuente a la hora de elegir la resolución es pensar que el tamaño del swf puede ser el mismo. Se elige siempre una <strong>resolución de pantalla</strong>, pero a estas medidas hay que restar otros elementos como el menú del sistema operativo y el tipo de navegador, teniendo en cuenta además la configuración de éstos (con/sin favoritos, barras de estado, barras alternativas como la de Google, Yahoo, etc). Horizontalmente apenas afecta, pero verticalmente bastante.</p>
<p>Yo, a día de hoy, suelo plantear las webs con una resolución mínima de 1024&#215;768. Esto se traduce en un tamaño de 996&#215;578 para mis películas flash. Los 28px que resto horizontalmente lo hago contemplando la posibilidad de que se genere scroll vertical de sistema, mientras que los 90px que pierdo de altura corresponden a la configuración de un Firefox estándard en un sistema Windows.</p>
<blockquote><p><strong>Nota:</strong> a excepción de Chrome que cuenta con una interfaz muy limpia, el resto de navegadores cuentan con menús similares, así como los distintos sistemas operativos, que tienen un menú principal.</p>
<p>Como es imposible tener una medida que encaje en todas las combinaciones, es preferible dejar unos cuantos píxels de margen. A veces, por intentar ajustar demasiado se genera un scroll mínimo de 3 o 4 píxels que ensucia más que ayuda.</p></blockquote>
<p>Así pues, 996&#215;578 es el tamaño mínimo que garantizo para que una web se vea correctamente. Si el navegador tiene menos espacio para mostrar, se generará scroll de sistema.</p>
<blockquote><p><strong>Nota:</strong> hay gente que prefiere utilizar un scroll propio en flash. Yo no soy muy partidario para este caso concreto.</p></blockquote>
<h4>Swffit</h4>
<p>Para no tener que lidiar directamente con javascript, existe una utilidad llamada <a href="http://swffit.millermedeiros.com/" target="_blank">swffit</a> que permite fijar las medidas mínimas y máximas de tu película y se encarga de todo: mostrar el scroll cuando es necesario, reescalar la película para que ocupe todo el tamaño disponible, centrar la película, etc. Imprescindible.</p>
<h4>Resumiendo</h4>
<p>Los que trabajamos con Flash estamos acostumbrados a ver como la gente lo ataca por distintas razones. El tema de las resoluciones es una de ellas. Y con razón.</p>
<p>Resulta difícil de creer que programadores que hacen piezas tan espectaculares como para ganar un <em>Favourite</em> no tengan en cuenta este punto. Por no hablar de todos aquellos que &#8220;aprenden flash en 2 días&#8221; y venden webs al vecino.</p>
<p>Si queremos quitarle la razón a los detractores de Flash, tanto los diseñadores como los programadores debemos hacer las cosas bien, y esto pasa por empezar con las cosas básicas.</p>
<hr />
<p><small>
<a href="http://llops.com/blog/2009/09/19/medidas-y-resoluciones-en-flash/#comments">5 comentarios</a>
<br/>
<a href="http://twitter.com/share?url=http://llops.com/blog/2009/09/19/medidas-y-resoluciones-en-flash/&text=Leyendo%20%22Medidas y resoluciones en Flash%22&via=llops%20blog">Compartir en Twitter</a> | 
<a href="http://www.facebook.com/sharer.php?u=http://llops.com/blog/2009/09/19/medidas-y-resoluciones-en-flash/&t=Medidas y resoluciones en Flash">Compartir en Facebook</a>

<br/><br/>
© <a href="http://llops.com/blog">llops blog</a> 2009 
</small></p>]]></content:encoded>
			<wfw:commentRss>http://llops.com/blog/2009/09/19/medidas-y-resoluciones-en-flash/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Env&#237;o de im&#225;genes y datos con AS3</title>
		<link>http://llops.com/blog/2009/01/18/envio-de-imagenes-y-datos-con-as3/</link>
		<comments>http://llops.com/blog/2009/01/18/envio-de-imagenes-y-datos-con-as3/#comments</comments>
		<pubDate>Sun, 18 Jan 2009 21:26:27 +0000</pubDate>
		<dc:creator>llops</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[bitmapData]]></category>
		<category><![CDATA[boundary]]></category>
		<category><![CDATA[byteArray]]></category>
		<category><![CDATA[codificar]]></category>
		<category><![CDATA[GET]]></category>
		<category><![CDATA[imagen]]></category>
		<category><![CDATA[jpg]]></category>
		<category><![CDATA[multipart]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[png]]></category>
		<category><![CDATA[POST]]></category>

		<guid isPermaLink="false">http://llops.com/blog/?p=47</guid>
		<description><![CDATA[En el anterior post, en el apartado El envío de la postal, comentaba que parte del desarrollo consistía en enviar una imagen y distintas variables de Flash al servidor, pero que en AS3 no había una forma sencilla de hacer un envío multipart y habíamos recurrido a la potente librería as3httpclientlib para conseguirlo. A pesar [...]]]></description>
			<content:encoded><![CDATA[<p>En el <a href="http://llops.com/blog/2008/12/23/felicitacion-navidad-ikea/" target="_blank">anterior post</a>, en el apartado <em>El envío de la postal</em>, comentaba que parte del desarrollo consistía en enviar una imagen y distintas variables de Flash al servidor, pero que en AS3 no había una forma sencilla de hacer un envío <em>multipart</em> y habíamos recurrido a la potente librería <a href="http://code.google.com/p/as3httpclientlib/">as3httpclientlib</a> para conseguirlo.</p>
<p>A pesar de que dicha librería funciona perfectamente, lo hace todo mediante sockets, cosa que añade un grado (o varios, según el caso) de dificultad. Como para el proyecto de IKEA no íbamos sobrados de tiempo, no le di más vueltas y la utilicé, pero me quedó la espinita de si no había maneras más sencillas de hacerlo, y desde entonces he estado mirando todo lo relacionado con el tema de envíos desde Flash. Este artículo recoge y explica distintas soluciones que he ido encontrando.</p>
<p>Empezaremos con el caso más sencillo, que es enviar una imagen desde Flash al servidor.</p>
<p><span id="more-47"></span></p>
<h4>Enviar una imagen con AS3</h4>
<p>En AS3 contamos con la clase <em>URLRequest</em>, que combinándola con otros métodos para hacer envíos, permite mandar datos como texto, como variables o como binario. Así pues, se puede pasar cualquier archivo como binario, pero para ello primero hay que codificarlo. En el caso de un jpg o un png, podemos utilizar la librería de Adobe <a href="http://code.google.com/p/as3corelib/">as3corelib</a>, que cuenta con las clases <em>JPGEncoder</em> y <em>PNGEncoder</em>, y a partir de un <em>BitmapData</em> (el formato interno de Flash para almacenar datos de una imagen) te genera un <em>ByteArray</em> con la información.</p>
<p>Como ejemplo vamos a crear una imagen a partir de un movieclip que tenemos en el escenario y a enviarla a un php para que la muestre:</p>
<div class="linea-extra"></div>
<p>
<object width="300" height="150">
<param name="movie" value="http://llops.com/blog/content/articulos/ene09/envio_simple.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="http://llops.com/blog/content/articulos/ene09/envio_simple.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/ene09/envio_simple.zip" target="_blank">Descargar ejemplo</a></p>
<blockquote><p><strong>Nota:</strong> para que funcione el ejemplo, tanto el swf como el php se deben encontrar en el mismo dominio.</p></blockquote>
<p>El código del ejemplo está comentado aunque es bastante sencillito, y la única tarea realmente dura la hace la clase <em>JPGEncoder</em>. Vamos a echar un vistazo a las partes relevantes:</p>
<p>Se toma un "pantallazo" dibujando el movieclip en un bitmapData</p>
<div class="igBar"><span id="lactionscript3-8"><a href="#" onclick="javascript:showCodeTxt('actionscript3-8'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-8">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> bmpData:<span style="color: #000099;">BitmapData</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">BitmapData</span><span style="color: #555;">&#40;</span>foto_mc.<span style="color: #555;">width</span>, foto_mc.<span style="color: #555;">height</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">bmpData.<span style="color: #555;">draw</span><span style="color: #555;">&#40;</span>foto_mc<span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Se crea un objeto <em>JPGEncoder</em>. El parámetro indica la calidad de la imagen (sobre 100). Se codifica el <em>bitmapData</em> y se asigna a un <em>byteArray</em>.</p>
<div class="igBar"><span id="lactionscript3-9"><a href="#" onclick="javascript:showCodeTxt('actionscript3-9'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-9">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> jpg_codificado:JPGEncoder = <span style="color: #1518ff;">new</span> JPGEncoder<span style="color: #555;">&#40;</span><span style="color: #FF0000;color:#000099;">99</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> <span style="color: #000099;">byteArray</span>:<span style="color: #000099;">ByteArray</span> = jpg_codificado.<span style="color: #555;">encode</span><span style="color: #555;">&#40;</span>bmpData<span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p>
El tipo de cabecera indica que se trata de un archivo binario</p>
<div class="igBar"><span id="lactionscript3-10"><a href="#" onclick="javascript:showCodeTxt('actionscript3-10'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-10">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> cabecera:<span style="color: #000099;">URLRequestHeader</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">URLRequestHeader</span><span style="color: #555;">&#40;</span><span style="color: #555;">"Content-type"</span>, <span style="color: #555;">"application/octet-stream"</span><span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p>
Se crea un objeto <em>URLRequest</em> que contiene toda la información referente al envío. El parámetro data es que el que contiene la foto codificada, y el parámetro vFoto el nombre que le queramos asignar (no es obligatorio).</p>
<div class="igBar"><span id="lactionscript3-11"><a href="#" onclick="javascript:showCodeTxt('actionscript3-11'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-11">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> urlFoto:<span style="color: #000099;">URLRequest</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">URLRequest</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">urlFoto.<span style="color: #555;">requestHeaders</span>.<span style="color: #555;">push</span><span style="color: #555;">&#40;</span>cabecera<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">urlFoto.<span style="color: #555;">method</span> = <span style="color: #000099;">URLRequestMethod</span>.<span style="color: #555;">POST</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">urlFoto.<span style="color: #555;">data</span> = <span style="color: #000099;">byteArray</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">urlFoto.<span style="color: #555;">url</span> = _ruta + <span style="color: #555;">"?vFoto="</span> + _nombre_foto; </div>
</li>
</ol>
</div>
</div>
</div>
<p>
En este ejemplo se manda abrir el php en una ventana en blanco, pero lo normal sería utilizar un objeto <em>URLLoader</em> para enviar la información y procesar el resultado.</p>
<div class="igBar"><span id="lactionscript3-12"><a href="#" onclick="javascript:showCodeTxt('actionscript3-12'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-12">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">navigateToURL<span style="color: #555;">&#40;</span>urlFoto, <span style="color: #555;">"_blank"</span><span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p>
Por último, el php se encarga de recibir la imagen y mostrarla por pantalla.</p>
<blockquote><p><strong>Nota:</strong> como son operaciones que mucha gente busca, en el php he incluido una rutina para guardar el archivo en el servidor y otra que da la opción de descargar el fichero al disco duro.</p></blockquote>
<h4>Limitaciones de este método</h4>
<p>Para cosas muy sencillas el ejemplo anterior es perfecto, pero normalmente, cuando se envía un archivo se suele acompañar también de variables que contienen información. Al asignar a la propiedad <em>data</em> el <em>byteArray</em>, perdemos todas las opciones de adjuntar un objeto con dicha información.</p>
<p>Un "truquillo" sería enviar la foto mediante POST y aprovechar la url para pasar variables por GET, igual que hemos hecho con el nombre del archivo. Por ejemplo:</p>
<div class="igBar"><span id="lactionscript3-13"><a href="#" onclick="javascript:showCodeTxt('actionscript3-13'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-13">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">urlFoto.<span style="color: #555;">url</span> = <span style="color: #555;">"ruta/form.php?vFoto=avatar.jpg&amp;amp;nombre=llops&amp;amp;edad=28"</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p>
De todas formas, no es el sistema más limpio, y mejor usarlo como un recurso puntual para pasar pocos parámetros (aunque no tiene nada que ver con el <a href="http://www.w3.org/2001/tag/doc/get7#myths" target="_blank">mito</a> de los 256 caracteres).</p>
<p>Lo ideal es poder hacer un envío <a title="Wikipedia - multipart" href="http://es.wikipedia.org/wiki/MIME#Mensajes_Multiparte" target="_blank">multipart</a>, igual que se hace con los formularios html o como lo hace la propia clase de AS3 <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/FileReference.html" target="_blank">FileReference</a>. Y buscando buscando, di con una clase que sirve perfectamente para el propósito...</p>
<h4>Enviando una imagen y datos mediante la clase UploadPostHelper</h4>
<p>La clase <a href="http://marstonstudio.com/?p=36" target="_blank">UploadPostHelper</a> te permite pasar un nombre de archivo, un <em>ByteArray</em> y un <em>Object</em> y devuelve otro <em>ByteArray</em> con todo el contenido codificado que podemos enviar como <em>data</em>.</p>
<div class="linea-extra"></div>
<p>
<object width="300" height="150">
<param name="movie" value="http://llops.com/blog/content/articulos/ene09/envio_multiple.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="http://llops.com/blog/content/articulos/ene09/envio_multiple.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/ene09/envio_multiple.zip" target="_blank">Descargar ejemplo</a></p>
<p>El uso sigue siendo muy sencillo: la mayoría de pasos del ejemplo anterior son los mismos, y <em>UploadPostHelper</em> hace todo el trabajo sucio de forma transparente:</p>
<div class="igBar"><span id="lactionscript3-14"><a href="#" onclick="javascript:showCodeTxt('actionscript3-14'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-14">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> urlFicha:<span style="color: #000099;">URLRequest</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">URLRequest</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">urlFicha.<span style="color: #555;">contentType</span> = <span style="color: #555;">'multipart/form-data; boundary='</span> + UploadPostHelper.<span style="color: #555;">getBoundary</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">urlFicha.<span style="color: #555;">requestHeaders</span>.<span style="color: #555;">push</span><span style="color: #555;">&#40;</span> <span style="color: #1518ff;">new</span> <span style="color: #000099;">URLRequestHeader</span><span style="color: #555;">&#40;</span> <span style="color: #555;">'Cache-Control'</span>, <span style="color: #555;">'no-cache'</span> <span style="color: #555;">&#41;</span> <span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">urlFicha.<span style="color: #555;">method</span> = <span style="color: #000099;">URLRequestMethod</span>.<span style="color: #555;">POST</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">urlFicha.<span style="color: #555;">data</span> = UploadPostHelper.<span style="color: #555;">getPostData</span><span style="color: #555;">&#40;</span>_nombre_foto, <span style="color: #000099;">byteArray</span>, datos<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">urlFicha.<span style="color: #555;">url</span> = _ruta; </div>
</li>
</ol>
</div>
</div>
</div>
<p>
En la segunda linea vemos que se establece el <em>contentType</em> como multipart. El <em>boundary</em> es un <em>string</em> que se genera en cada envío aleatoriamente y sirve para delimitar las diferentes partes del envío. En la cuarta linea es donde se llama al método getPostData, que nos devuelve un array con todos los datos pasados.</p>
<p>Se manda y... ya tenemos nuestro envío multipart. ¿Fácil, no?</p>
<h4>Mandando varios archivos</h4>
<p>Y aunque el método anterior sirve para el 90% de los casos, para rizar el rizo, ya sólo falta poder enviar varios archivos a la vez, cosa que no hace <em>UploadPostHelper</em>, pero sí la librería basada en sockets (<em>as3httpclientlib</em>).</p>
<p>Como no vi nada similar pensé en modificar la clase <em>UploadPostHelper</em>, ya que el trabajo duro estaba hecho, y lo único que falta es permitir añadir nuevas partes, pero para mi sorpresa, mientras me documentaba, he encontrado a alguien que ha escrito una clase con el mismo objetivo hace sólo dos días :)</p>
<p>El post en cuestión es este: <a title="http://blog.inspirit.ru/?p=139" href="http://blog.inspirit.ru/?p=139">http://blog.inspirit.ru/?p=139</a> y el ejemplo es bastante claro, así que no redundaré para no hacer esto más largo.</p>
<h4>Resumiendo</h4>
<p>A medida que las capacidades de <em>Flash Player</em> crecen, cada vez es más corriente generar imágenes en el mismo player, y también aumenta la necesidad de poder exportarlas. Pero el tema no se reduce sólo a jpgs, sino también a otro tipo de archivos como pdf, zip o mp3.</p>
<p>Gracias a la potencia de AS3 y al esfuerzo de muchas personas que crean todo tipo de librerías y utilidades, llevar a cabo esta tarea se convierte en un paseo, pero detrás hay un trabajo realmente complejo (sólo hay que echar un vistazo a dichas clases).</p>
<p>Con este artículo espero haber allanado un poco el camino por si alguna vez te tienes que enfrentar con el tema.</p>
<hr />
<p><small>
<a href="http://llops.com/blog/2009/01/18/envio-de-imagenes-y-datos-con-as3/#comments">14 comentarios</a>
<br/>
<a href="http://twitter.com/share?url=http://llops.com/blog/2009/01/18/envio-de-imagenes-y-datos-con-as3/&text=Leyendo%20%22Env&iacute;o de im&aacute;genes y datos con AS3%22&via=llops%20blog">Compartir en Twitter</a> | 
<a href="http://www.facebook.com/sharer.php?u=http://llops.com/blog/2009/01/18/envio-de-imagenes-y-datos-con-as3/&t=Env&iacute;o de im&aacute;genes y datos con AS3">Compartir en Facebook</a>

<br/><br/>
© <a href="http://llops.com/blog">llops blog</a> 2009 
</small></p>]]></content:encoded>
			<wfw:commentRss>http://llops.com/blog/2009/01/18/envio-de-imagenes-y-datos-con-as3/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Consejos para trabajar con Flash y AS3 en equipo</title>
		<link>http://llops.com/blog/2008/11/10/consejos-para-trabajar-con-flash-y-as3-en-equipo/</link>
		<comments>http://llops.com/blog/2008/11/10/consejos-para-trabajar-con-flash-y-as3-en-equipo/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 08:37:41 +0000</pubDate>
		<dc:creator>llops</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[biblioteca]]></category>
		<category><![CDATA[flash cs3]]></category>
		<category><![CDATA[Flash Player]]></category>
		<category><![CDATA[frameCode]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[strictMode]]></category>

		<guid isPermaLink="false">http://llops.com/blog/?p=43</guid>
		<description><![CDATA[Al contrario que en el 2007, donde todo lo que hice en CS3 y AS3 fue en solitario, durante este año he trabajado en varios proyectos en equipo, tanto con compañeros de mi agencia como estudios o freelances. En general, me considero bastante flexible a la hora de trabajar con otros programadores y no intento [...]]]></description>
			<content:encoded><![CDATA[<p>Al contrario que en el 2007, donde todo lo que hice en CS3 y AS3 fue en solitario, durante este año he trabajado en varios proyectos en equipo, tanto con compañeros de mi agencia como estudios o freelances. En general, me considero bastante flexible a la hora de trabajar con otros programadores y no intento imponer nada (y más en el mundillo Flash, donde hay mil maneras distintas de alcanzar un objetivo), pero aún así, he llegado a la conclusión de que hacen falta una serie de "buenas prácticas" para que el proceso no sea un sufrimiento para el resto.</p>
<p>Los puntos que voy a explicar me parecen igual de válidos si se trabaja solo, pero obviamente la repercusión es mucho menor porque no afecta a nadie más. Y con trabajar en equipo no me refiero sólo a dos o más personas simultáneamente, sino también aquellos desarrollos que un día empieza uno y luego ha de continuar otro.</p>
<p><span id="more-43"></span></p>
<h4>Separar código fuente y archivos finales</h4>
<p>Hace no muchos años era frecuente ver proyectos como el siguiente</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/nov08/no_ordenados.jpg" alt="" /></p>
<p>donde los fla, html, xml, jpg, etcétera convivían mezclados. Y también era normal que allá donde hubiera un fla estuviera su correspondiente swf. Evidentemente, esto no facilita nada la navegación por el proyecto ni poder mover el directorio de producción entre diferentes servidores. Y no todo el mundo ha conseguido desprenderse de este viejo hábito.</p>
<p>A no ser que sea un proyecto muy pequeño (un banner o similar), es imprescindible contar con carpetas separadas para el código fuente y para los archivos finales. Yo suelo utilizar como nomenclatura <strong>src</strong> y <strong>bin</strong>, o también <strong>source</strong> y <strong>deploy</strong>.</p>
<h4>Bibliotecas ordenadas</h4>
<p>¿Hay alguien que no odie abrir un fla y encontrarse cientos de símbolos desperdigados en la biblioteca? En todos los años que llevo utilizando Flash he visto muy poca gente que le dedique tiempo a ordenar <strong>coherentemente</strong> la librería.</p>
<p>El sistema que suelo utilizar es un árbol de carpetas con la misma estructura que siguen los movieclips en la linea de tiempo. Me gusta porque al tener una relación 1 a 1 es facilísimo encontrar cualquier elemento y navegar por la biblioteca como si fuera el escenario, aunque por contra obliga a generar demasiadas carpetas y niveles y hay que ser muy exhaustivo.</p>
<p>Tampoco me desagrada ordenar por grupos lógicos (por ejemplo, una carpeta para el "Panel de Login", otra para el "Menú de navegación", etc) siempre y cuando no haya demasiado contenido. En ese caso, prefiero añadir más directorios intermedios.</p>
<h4>Código en timeline y en la clase</h4>
<p>Normalmente intento reducir al mínimo el código en linea de tiempo, aunque tampoco me opongo en rotundo (a veces es mejor picar 2 o 3 instrucciones en un frame que no generar una clase nueva).</p>
<p>También en algunas ocasiones hay que<strong> </strong>poner código en frames en movieclips<strong> que cuentan con su propia clase</strong>. Cuando un mc tiene una clase asociada ésta se ejecuta en el primer frame, así que, por ejemplo, no podemos escuchar un TextInput que se encuentra en el frame 5. Tendremos que esperar hasta alcanzar dicho frame para poder referenciarlo. Hay que tener mucho cuidado con esto porque puede hacer el seguimiento muy difícil al estar divido el código en 2 sitios.</p>
<p>A mi parecer, lo más "limpio" es dispachar eventos notificando en que punto nos encontramos, e intentar que el framecode no se encargue de hacer demasiadas tareas.</p>
<p>Se haga lo que se haga, es muy importante comentar <strong>tanto en el frame como en la clase</strong>, indicando quién hace qué, porque sino te puedes volver realmente loco.</p>
<h4>Instanciando desde la biblioteca</h4>
<p>Me parece genial que en AS3 ya no se utilice más <em>attachMovie</em> y que siempre haya que generar nuevas instancias con el operador <em>new</em>. De todas maneras, la ventaja de <em>attachMovie</em> era que inmediatamente sabías que se utilizaba una instancia de la biblioteca, y ahora no. En este caso, me parece más que interesante comentar indicando que la clase se encuentra en la librería.</p>
<p>Y de manera contraria, me parece también necesario comentar al inicio las clases que tienen un movieclip o un sprite asociado, ya que sino lo sabes puedes perder mucho tiempo buscando en el resto de clases quién instancia cuando resulta que simplemente se ha arrastrado un elemento al escenario.</p>
<h4>NO declarar instancias del escenario automáticamente</h4>
<p>Ya hace tiempo dediqué un <a title="Añadiendo movieclips manualmente al escenario" href="http://llops.com/blog/2007/12/01/programando-en-as3-desde-flash-cs3-i/#part2" target="_blank">extenso apartado</a> a explicar en que consiste esta opción que nos facilita Flash CS3 y cómo funciona internamente:</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/nov08/settings_instance.jpg" alt="" /></p>
<p>Básicamente nos permite no tener que declarar en nuestra clase propia los movieclips que se han añadido manualmente al escenario. Personalmente me parece un error, ya que luego no sabes de dónde salen los objetos, y crea muchísima más confusión si el código no es tuyo.</p>
<p>Siempre, al principio de cada clase, declaro todos los objetos del escenario:</p>
<div class="igBar"><span id="lactionscript3-16"><a href="#" onclick="javascript:showCodeTxt('actionscript3-16'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-16">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #F0F; font-style: italic;">// MC en el escenario</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">var</span> fullscreen_mc:<span style="color: #000099;">MovieClip</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">var</span> opciones_mc:<span style="color: #000099;">MovieClip</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">var</span> panel_mc:<span style="color: #000099;">MovieClip</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">var</span> slider_radio:Slider;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">var</span> check_circular:CheckBox; </div>
</li>
</ol>
</div>
</div>
</div>
<p>
así, de un vistazo se sabe qué instancias se encuentran en el fla, y además habilita el código de autocompletado en editores como FlashDevelop.</p>
<h4>Activar modo estricto</h4>
<p>Como ya sabemos, ActionScript cuenta con dos modos para compilar un programa: el modo estricto y el modo estándar. En modo estricto el compilador resuelve los errores tanto en tiempo de compilación como en tiempo de ejecución, con lo que nos proporciona mucha más información si algo no funciona como debería.</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/nov08/settings_strict_mode.jpg" alt="" /></p>
<p>Uno de los mayores problemas del modo estricto es que muchas de las fallas que detecta no son errores "reales", simplemente es que el compilador no tiene información suficiente sobre qué está pasando y no nos deja continuar. Es aquí donde entra la tediosa tarea de castear objetos. Otras veces el problema puede ser tan insignificante como usar dos veces una variable en una función (la típica i en un for).</p>
<p>Hay programadores que optan por desactivar esta opción evitándose este tipo de errores. Aunque al principio se puede pensar que se gana tiempo, nada más lejos de la realidad: cuesta muchísimo más encontrar errores tontos (del tipo llamar a una función que no existe o pasar un número incorrecto de argumentos) que ser minucioso con el código que se escribe.</p>
<p>Siempre pongo el paralelismo de las variables en AS1 cuando no se tipaban: era mucho más cómodo no tener que decir si una propiedad era un String o un Int, pero en cuanto uno se acostumbra los beneficios son muchísimos más. No me imagino a nadie que programe en AS3 que no utilice el tipado. Lo mismo debería ocurrir con el modo estricto.</p>
<h4>Resumiendo</h4>
<p>En el título del post hablo de "consejos" porque entiendo que no todo el mundo estará de acuerdo con que los puntos son tan importantes, pero para mí, van a ser un requisito en futuros proyectos en que trabaje con más gente.</p>
<p>Me parece que seguir estas pautas no supone un gran sacrificio, y realmente pueden ahorrar mucho mucho tiempo a otras personas.</p>
<hr />
<p><small>
<a href="http://llops.com/blog/2008/11/10/consejos-para-trabajar-con-flash-y-as3-en-equipo/#comments">14 comentarios</a>
<br/>
<a href="http://twitter.com/share?url=http://llops.com/blog/2008/11/10/consejos-para-trabajar-con-flash-y-as3-en-equipo/&text=Leyendo%20%22Consejos para trabajar con Flash y AS3 en equipo%22&via=llops%20blog">Compartir en Twitter</a> | 
<a href="http://www.facebook.com/sharer.php?u=http://llops.com/blog/2008/11/10/consejos-para-trabajar-con-flash-y-as3-en-equipo/&t=Consejos para trabajar con Flash y AS3 en equipo">Compartir en Facebook</a>

<br/><br/>
© <a href="http://llops.com/blog">llops blog</a> 2008 
</small></p>]]></content:encoded>
			<wfw:commentRss>http://llops.com/blog/2008/11/10/consejos-para-trabajar-con-flash-y-as3-en-equipo/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>EnterFrame vs Timer (I)</title>
		<link>http://llops.com/blog/2008/07/27/enterframe-vs-timer-i/</link>
		<comments>http://llops.com/blog/2008/07/27/enterframe-vs-timer-i/#comments</comments>
		<pubDate>Sun, 27 Jul 2008 16:00:59 +0000</pubDate>
		<dc:creator>llops</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[enterFrame]]></category>
		<category><![CDATA[Flash Player]]></category>
		<category><![CDATA[framerate]]></category>
		<category><![CDATA[render]]></category>
		<category><![CDATA[setInterval]]></category>
		<category><![CDATA[Timer]]></category>
		<category><![CDATA[updateAfterEvent]]></category>

		<guid isPermaLink="false">http://llops.com/blog/?p=35</guid>
		<description><![CDATA[Hace ya varios años, en una época en la que la web estaba poblada de páginas estáticas y todo el movimiento se reducía a los gif, un programa llamado FutureSplash consiguió sorprender a todos por su increíble capacidad para la animación. Emulando el sistema de cinematografía, basado en proyectar fotogramas de forma rápida y sucesiva [...]]]></description>
			<content:encoded><![CDATA[<p>Hace ya varios años, en una época en la que la web estaba poblada de páginas estáticas y todo el movimiento se reducía a los gif, un programa llamado FutureSplash consiguió sorprender a todos por su increíble capacidad para la animación.</p>
<p>Emulando el sistema de cinematografía, basado en proyectar fotogramas de forma rápida y sucesiva para lograr la sensación de movimiento, FutureSplash incorporaba una linea de tiempo en la que se podía dibujar frame a frame para reproducir luego la película.</p>
<p>Un año más tarde, ese revolucionario programa fue adquirido por Macromedia y nació Flash 1.0, para acabar evolucionando actualmente en Flash CS3, de la mano de Adobe. Y por sorprendente que parezca, nueve versiones después, la filosofía para generar animación se ha mantenido intacta.</p>
<p>Al margen de la animación tradicional en linea de tiempo, la otra forma de generar animación es mediante código, y en ActionScript sí que ha ido evolucionando el tema:</p>
<ul>
<li>En Flash 5 se introdujo el archiconocido <em>enterFrame.</em></li>
<li>En Flash MX nos obsequiaron con <em>setInterval</em> (lo recuerdo como una gran novedad).</li>
<li>Y ya en AS3, se ha apostado por la clase <em>Timer</em> como sucesora de <em>setInterval</em>.</li>
</ul>
<p>Así pues, en Flash 5, para animar mediante código se utilizaba <em>enterFrame</em>, pero con la introducción de <em>setInterval</em> la comunidad empezó a dividirse entre partidarios y detractores de uno y otro sistema. Es fácil encontrar discusiones en blogs, foros y listas sobre este tema, y personalmente he perdido la cuenta de cuantas veces he debatido sobre ello.</p>
<p>En este artículo vamos a estudiar la clase <em>Timer</em> (setInterval está desaconsejada, pero la lógica se puede aplicar igualmente) y el evento <em>enterFrame</em>, con la esperanza de poder definir cuándo es mejor usar una u otra.</p>
<p><span id="more-35"></span></p>
<h4>EnterFrame</h4>
<p><em>Flash Player</em> cuenta con un motor interno que ejecuta un frame tras otro de forma continua, incluso en películas que no tienen linea de tiempo o que están detenidas. El evento <em>enterFrame</em> está sincronizado con el <em>framerate</em> de la película y se lanza cada vez que el motor alcanza un nuevo frame.</p>
<p>Los frames se cuentan por segundos (<em>fps</em>), y desde el <em>IDE</em> admite el siguiente rango de valores: 0.01 a 120. En AS3 se puede establecer por primera vez el <em>framerate</em> vía código, permitiendo aumentar el valor hasta 1000 fps.</p>
<p>Cualquier objeto que descienda de <em>DisplayObject</em> se puede suscribir (y desuscribir) a un evento <em>enterFrame</em>, pero no se tiene ningún control sobre él, se genera de forma natural en cada película.</p>
<h4>Timer</h4>
<p>Como comentaba, la clase <em>Timer</em> es una novedad de AS3. Nos permite crear un objeto que periódicamente llama a una función, pero en vez de estar ligado a la velocidad de la película, lo hace definiendo un intervalo de tiempo. De esta manera podemos indicar que un objeto se mueva cada 5 milésimas, 5 segundos o 5 minutos.</p>
<p>A un objeto <em>Timer</em>, junto con la frecuencia, se le puede indicar cuantas veces se debe ejecutar (por ejemplo, llamar a una función 5 veces cada medio segundo), y además cuenta con métodos <em>start</em>, <em>stop</em> y <em>reset</em> para controlarlo y con eventos que indican cada vez que se dispara la función o cuándo se ha completado un ciclo de llamadas.</p>
<p>Una persona sin experiencia en ActionScript a la que se le plantearan los dos mecanismos elegiría utilizar la clase <em>Timer</em>, dada todas las ventajas que aporta sobre <em>enterFrame</em>. Pero para sacar conclusiones, antes hay que conocer los mecanismos internos que tiene Flash Player para actualizar la pantalla.</p>
<h4>Actualizando la pantalla</h4>
<p>Hace ya alguna semanas escribí un post titulado <a href="http://llops.com/blog/2008/05/24/el-sistema-de-renderizado-de-flash-player/" target="_blank">El sistema de renderizado del Flash Player</a>. Ese post estaba pensado inicialmente para explicarlo en este apartado, pero debido a lo extenso que estaba quedando decidí hacer un artículo al margen. Sino lo has leído o no lo tienes fresco, es <del datetime="2008-07-27T15:57:19+00:00">aconsejable</del> imprescindible que le eches un vistazo antes de continuar.</p>
<p>Como recordatorio nos quedaremos con esta imagen:</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/jul08/render3.jpg" alt="" /></p>
<p class="img-comment">Procesamiento de 1 frame a 1 fps con un evento EnterFrame</p>
<p>Al entrar en un frame se dispara el evento <em>enterFrame</em>, después se ejecuta el código del frame y se espera hasta que que llega la hora de renderizar la pantalla.</p>
<h4>Un error muy común</h4>
<p>Uno de los errores frecuentes que cometen muchos programadores (y no sólo novatos) es utilizar un <em>Timer</em> porque pueden poner valores muy bajos y hacer así más comprobaciones por segundo.</p>
<p>Por ejemplo, un clásico, utilizarlo para comprobar colisiones entre objetos:</p>
<div class="igBar"><span id="lactionscript3-20"><a href="#" onclick="javascript:showCodeTxt('actionscript3-20'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-20">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> t:<span style="color: #000099;">Timer</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">Timer</span><span style="color: #555;">&#40;</span><span style="color: #FF0000;color:#000099;">1</span><span style="color: #555;">&#41;</span>; <span style="color: #F0F; font-style: italic;">// 1 milisegundo</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">t.<span style="color: #555;">addEventListener</span><span style="color: #555;">&#40;</span><span style="color: #000099;">TimerEvent</span>, comprobarColision<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">t.<span style="color: #555;">start</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">function</span> comprobarColision<span style="color: #555;">&#40;</span>e:<span style="color: #000099;">TimerEvent</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">if</span> <span style="color: #555;">&#40;</span>objetoA.<span style="color: #555;">colisiona</span><span style="color: #555;">&#40;</span>objetoB<span style="color: #555;">&#41;</span><span style="color: #555;">&#41;</span><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">objetoA.<span style="color: #555;">cambiaDireccion</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">objetoB.<span style="color: #555;">cambiaDireccion</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Con la necesidad de saber inmediatamente cuándo los dos objetos se están tocando, lo comprobamos mil veces por segundo.</p>
<p>Este pensamiento conlleva dos grandes problemas:</p>
<ol>
<li>Ninguna máquina te va a dar un rendimiento suficiente con un valor tan bajo.</li>
<li>Aunque la máquina lo diera, sería inútil, ya que <strong>el renderizado de pantalla depende del framerate.</strong></li>
</ol>
<p>Para mayor claridad, vamos a estudiar estos dos problemas en apartados independientes.</p>
<h4>Problema 1</h4>
<p>Un objeto <em>Timer</em>, a pesar de funcionar independientemente del <em>framerate</em>, depende en todo momento de la velocidad de procesamiento de la máquina, y es por eso que no es capaz de garantizar el valor asignado.</p>
<p>Por ejemplo, pongamos un caso perfecto en que tenemos puesto durante 10 segundos un <em>Timer</em> a 1 milisegundo: realizaría 10.000 llamadas a una función. Si esta película la ponemos en un ordenador que esté ocupado por otros programas, quizá sólo sea capaz de realizar 6.000 llamadas en el mismo tiempo.</p>
<p>Como no podemos garantizar el rendimiento, es importante no forzar la cpu con valores muy bajos. He aquí una tabla de valores en milisegundos y su correspondencia en fps:</p>
<table class="centered" border="1" cellspacing="0" cellpadding="5" width="300">
<tbody>
<tr>
<td valign="top"><strong>Valor del</strong> <strong>Timer</strong></td>
<td valign="top"><strong>Framerate</strong></td>
</tr>
<tr></tr>
<tr>
<td valign="top">1 ms</td>
<td valign="top">1.000 fps</td>
</tr>
<tr>
<td valign="top">10 ms</td>
<td valign="top">100 fps</td>
</tr>
<tr>
<td valign="top">20 ms</td>
<td valign="top">50 fps</td>
</tr>
<tr>
<td valign="top">30 ms</td>
<td valign="top">33'3 fps</td>
</tr>
<tr>
<td valign="top">50 ms</td>
<td valign="top">20 fps</td>
</tr>
<tr>
<td width="88" valign="top">100 ms</td>
<td width="110" valign="top">10 fps</td>
</tr>
</tbody>
</table>
<p>Como podemos ver, valores por debajo de 10 ms son prohibitivos. Cuanto mayor sea el número de milisegundos mejor podremos garantizar el equilibrio de nuestra película en distintos ordenadores.</p>
<h4>Problema 2</h4>
<p>Imaginemos un hipotético caso en que nuestra máquina es capaz de procesar a 1 milisegundo y simulemos el ejemplo en que dos bolas colisionan:</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/jul08/simulacion_colision.jpg" alt="" /></p>
<p class="img-comment">Película a 1 fps y comprobación de colisión mediante Timer a 1 milisegundo</p>
<p>Los objetos están ligados al motor central del swf, así que en cada frame se procesa el código y se actualiza la pantalla. Por otro lado, de forma independiente, con un <em>Timer</em> vamos comprobando si hay colisión. Es muy fácil ver que estamos haciendo miles de comprobaciones inútiles. E incluso en el frame 3, dónde por fin el <em>Timer</em> detecta la colisión, aunque a nivel de código se haya procesado en el milisegundo 1, no va a tener representación visual hasta el milisegundo 1000 (después del ciclo de renderizado).</p>
<p>El mismo código coordinado con <em>enterFrame</em> nos hubiera dado 1 colisión de 4 comprobaciones, en vez de 1 de 4000.</p>
<p>Siempre que se ejecute código que tenga una representación por pantalla, si lo hacemos en un <em>enterFrame</em> estamos asegurando que<strong> tenemos una relación 1 a 1 entre la ejecución y la visualización en un frame</strong>.</p>
<blockquote><p><strong>Nota:</strong> para ejemplificar el problema de los valores bajos en un <em>Timer</em>, he escogido la situación más exagerada: 1 fps y 1 milisegundo. De todas formas, con otros valores más reales, como 24 fps y 10-20 milisegundos, la cantidad de recursos desperdiciados sigue siendo muy grande.</p></blockquote>
<h4>Solucionando los problemas</h4>
<p>Ya hemos visto que para solucionar el problema 1 no debemos utilizar valores que fuercen excesivamente la máquina: hay que valorar la cantidad de código que se procesa en el listener del <em>Timer</em>, durante cuánto tiempo, si la película ya está consumiendo recursos...</p>
<p>Para el segundo punto, hay una solución que ya comenté en el artículo del render: el método <em>UpdateAfterEvent</em>, que se puede invocar en las clases <em>MouseEvent</em>, <em>KeyboardEvent</em> y <em>TimerEvent</em>, y que fuerza al player a actualizar la pantalla. Su uso sería así:</p>
<div class="igBar"><span id="lactionscript3-21"><a href="#" onclick="javascript:showCodeTxt('actionscript3-21'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-21">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> t:<span style="color: #000099;">Timer</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">Timer</span><span style="color: #555;">&#40;</span><span style="color: #FF0000;color:#000099;">30</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">t.<span style="color: #555;">addEventListener</span><span style="color: #555;">&#40;</span><span style="color: #000099;">TimerEvent</span>, moverBola<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">t.<span style="color: #555;">start</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">function</span> moverBola<span style="color: #555;">&#40;</span>e:<span style="color: #000099;">TimerEvent</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">bola.<span style="color: #555;">x</span> += <span style="color: #FF0000;color:#000099;">0</span>.<span style="color: #FF0000;color:#000099;">5</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">e.<span style="color: #555;">updateAfterEvent</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Hay que notar que no sirve de nada utilizar este método si los objetos se siguen moviendo con el <em>framerate</em> de la película. En el ejemplo de la colisión, lo único que conseguiríamos es hacer las mil comprobaciones por segundo y refrescar la pantalla otras mil veces, pero si las bolas se mueven a 1fps lo único que conseguimos es empeorar todavía más el rendimiento de la película.</p>
<p>En cambio, si procesamos el código de movimiento en el listener del <em>Timer</em> y lo acompañamos con <em>updateAfterEvent</em>, tendremos un movimiento muy fluido.</p>
<p>Pero como suele pasar, una ventaja en un lado conlleva una desventaja en otro. En este caso, la fluidez del <em>Timer</em> más el update significa aumentar el número de ciclos de refresco de pantalla así como el número de ejecuciones del código, por lo que hay que usarlo prudentemente.</p>
<h4>Flash Player funciona con framerate </h4>
<p>A estas alturas parece obvio decirlo, pero Flash Player funciona bajo el compás que marca el <em>framerate</em>. Por ello, hay que tener en cuenta que si contamos <strong>con animación en linea de tiempo</strong>, <strong>sincronizar</strong> animación con código <strong>en un <em>enterFrame</em> es automático</strong>, pero hacerlo <strong>con un <em>Timer</em> es imposible</strong>.</p>
<p>Si tenemos una película que corre a 50 fps, una animación en el timeline de 500 frames y un <em>enterFrame</em> activado, en el caso ideal se recorren los 500 frames en 10 segundos lanzado 500 eventos <em>enterFrame</em>. Si el <em>framerate</em> no fuera real (ver apartado "Framerate real" en el <a href="http://llops.com/blog/2008/05/24/el-sistema-de-renderizado-de-flash-player/" target="_blank">artículo anterior</a>) y bajara por ejemplo a 25 fps, la película tardaría 20 segundos en ejecutarse, pero en el frame 228 se lanzaría el evento 228, y en 446 el 446, con lo que siempre tendremos sincronizada nuestra animación con nuestro código.</p>
<p>Sin embargo, debido a la naturaleza del <em>Timer</em>, aunque podamos limitar el número de eventos a 500 repeticiones y calcular el tiempo para que coincida con los 10 segundos que tardará el timeline, en cuanto la máquina no dé el valor exacto (que virtualmente es siempre), nuestro frame número 50 no corresponderá con el evento TIMER número 50.</p>
<p>Internet está poblada de películas Flash (animaciones, juegos, sites...) que no funcionan bien en todas las máquinas debido a que los programadores no tuvieron en cuenta este punto tan básico.</p>
<h4>La dependencia del Timer</h4>
<p>Unos apartados más arriba comentaba que el <em>Timer</em> funciona al margen del <em>framerate</em>, pero... ¿es esto cierto?. Para comprobarlo podemos crear una película a 120 fps y copiar el siguiente código en el primer frame:</p>
<div class="igBar"><span id="lactionscript3-22"><a href="#" onclick="javascript:showCodeTxt('actionscript3-22'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-22">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #F0F; font-style: italic;">// Inicializar contador</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> cont:<span style="color: #000099;">int</span> = <span style="color: #FF0000;color:#000099;">0</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #F0F; font-style: italic;">// Crear Bola</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> bola:<span style="color: #000099;">Sprite</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">Sprite</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">bola.<span style="color: #000099;">graphics</span>.<span style="color: #555;">beginFill</span><span style="color: #555;">&#40;</span>0xFF00FF<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">bola.<span style="color: #000099;">graphics</span>.<span style="color: #555;">drawCircle</span><span style="color: #555;">&#40;</span><span style="color: #FF0000;color:#000099;">0</span>,<span style="color: #FF0000;color:#000099;">0</span>,<span style="color: #FF0000;color:#000099;">10</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">bola.<span style="color: #000099;">graphics</span>.<span style="color: #555;">endFill</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">bola.<span style="color: #555;">y</span> = <span style="color: #FF0000;color:#000099;">100</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">addChild<span style="color: #555;">&#40;</span>bola<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #F0F; font-style: italic;">// Timer</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> t:<span style="color: #000099;">Timer</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">Timer</span><span style="color: #555;">&#40;</span><span style="color: #FF0000;color:#000099;">50</span>, <span style="color: #FF0000;color:#000099;">100</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">t.<span style="color: #555;">addEventListener</span><span style="color: #555;">&#40;</span><span style="color: #000099;">TimerEvent</span>.<span style="color: #000099;">TIMER</span>, mover<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">t.<span style="color: #555;">addEventListener</span><span style="color: #555;">&#40;</span><span style="color: #000099;">TimerEvent</span>.<span style="color: #555;">TIMER_COMPLETE</span>, fin<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">t.<span style="color: #555;">start</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #F0F; font-style: italic;">// Funciones</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">function</span> mover<span style="color: #555;">&#40;</span>e:<span style="color: #000099;">TimerEvent</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">cont++;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">bola.<span style="color: #555;">x</span> ++;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">function</span> fin<span style="color: #555;">&#40;</span>e:<span style="color: #000099;">TimerEvent</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">trace<span style="color: #555;">&#40;</span><span style="color: #555;">"Posición x:"</span>, bola.<span style="color: #555;">x</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Este código crea una bola en el escenario y mediante un <em>Timer</em> la mueve 1 pixel hacia la derecha cada 50 milisegundos un total de 100 veces. En otras palabras, pasados 5 segundos (100x50) la bola se habrá movido 100 pixels. Si ejecutamos veremos que realmente sucede así. ¿Pero qué sucede si en el mismo código cambiamos el <em>framerate</em> a 1 fps?</p>
<p>Al ejecutar la película comprobamos 3 cosas:</p>
<ol>
<li>La bola continúa desplazándose 100 pixels (correcto)</li>
<li>Debido al bajo <em>framerate</em> y que el renderizado ocurre cada segundo, el movimiento no es suave, sino que se visualiza a saltos (correcto)</li>
<li>La bola tarda bastante más de 5 segundos en recorrer los 100 pixels (¿?)</li>
</ol>
<p>Las dos primeras sentencias son lógicas, pero la tercera no debería serlo. Aunque por pantalla no se reflejen los cambios, el <em>Timer</em> debería procesarse en 5 segundos, ¿no? Pues no, porque <strong>incluso los <em>Timers</em> tienen dependencia del <em>framerate</em></strong>. La limitación consiste en que un <em>Timer</em> sólo puede dispararse como máximo 10 veces por cada ciclo de renderizado. Si nos fijamos en esta segunda prueba, la bola ha realizado exactamente 10 saltos antes de completar el recorrido, debido a que una película a 1fps puede alcanzar como máximo los 100 ms.</p>
<p>Sabiendo esto podríamos concluir con otra tabla entre el valor del <em>framerate</em> y la <em>dependencia</em> que crea en el <em>Timer</em>:</p>
<table class="centered" border="1" cellspacing="0" cellpadding="5" width="363">
<tbody>
<tr>
<td width="133" valign="top"><strong>Framerate</strong></td>
<td width="228" valign="top"><strong>Valor máximo del Timer</strong></td>
</tr>
<tr></tr>
<tr>
<td width="133" valign="top">1 fps</td>
<td width="228" valign="top">100 ms (= 10 veces por segundo)</td>
</tr>
<tr>
<td width="148" valign="top">10 fps</td>
<td width="228" valign="top">10 ms (= 100 veces por segundo)</td>
</tr>
<tr>
<td width="152" valign="top">100 fps</td>
<td width="228" valign="top">1 ms (= 1000 veces por segundo)</td>
</tr>
</tbody>
</table>
<p>Así pues, los valores que vimos en la primera tabla, realmente están supeditados a esta norma. Otra razón de peso para no poner valores muy bajos en el <em>Timer</em>.</p>
<h4>El consumo de memoria</h4>
<p>No hay que olvidar que con cada objeto <em>Timer</em> que se crea, se está reservando memoria, al contrario que con <em>enterFrame</em>, que no crea un nuevo objeto, sino que guarda una tabla de objetos suscritos.</p>
<p>Si creamos una clase <em>ObjetoAnimado</em> cuyo motor principal es la clase <em>Timer</em>, y luego creamos mil instancias de <em>ObjetoAnimado</em>, generaremos un consumo de memoria muy elevado, por lo que hay que tener cuidado cuando se trabaje con muchas instancias de la clase <em>Timer</em>.</p>
<blockquote><p><strong>Nota</strong>: Esto puede evitarse centralizando el código. En la segunda parte de este artículo se tratara este recurso.</p></blockquote>
<h4>Timer negatifo, nunca positifo</h4>
<p>Leído lo leído, va a resultar que la clase <em>Timer</em> sólo da problemas, y tampoco es así. El hecho de que esta clase funcione en relación al tiempo la hace especialmente útil, por ejemplo, realizando tareas cada ciertos periodos, ya que en caso de hacerse en un <em>enterFrame</em> resultarían repetitivas.</p>
<p>En el caso de la animación, la gran ventaja del <em>Timer</em> es que puede actuar independientemente sobre distintos objetivos, dándonos mucha más libertad que con <em>enterFrame</em>, en el cuál la velocidad es fija para toda la película (aunque en AS3 se pueda variar en tiempo de ejecución, sigue afectando a todos los elementos). Además, combinándolos con updateAfterEvent() se puede conseguir animaciones más fluidas.</p>
<p>Para sacarle el máximo provecho, sólo hay que entender su naturaleza y sus limitaciones.</p>
<h4>Resumiendo</h4>
<p>Como programadores, es un deber optimizar al máximo nuestros desarrollos, y en cualquier lenguaje visual, optimizar el código es un arte. A pesar de que año tras año la velocidad de procesamiento de los ordenadores aumenta, la memoria disponible cada vez es mayor, la AVM (ActionScript Virtual Machine) es más potente, etc. es frecuente ver swf que agotan los recursos del Player.</p>
<p>En ActionScript, un buena compresión del evento <em>enterFrame</em> y la clase <em>Timer</em> (combinado con el sistema de renderizado del Player), nos abre una gran puerta a desarrollar mejores programas. Con este artículo, espero haber puesto las bases de esa compresión, y allanar el camino para saber cuándo se debe utilizar uno u otro.</p>
<p>Dejo pendiente un segundo artículo en esta serie donde explicaré casos reales de uso, y en función de mi experiencia, mostraré cuál es la mejor manera de abordar el problema.</p>
<hr />
<p><small>
<a href="http://llops.com/blog/2008/07/27/enterframe-vs-timer-i/#comments">9 comentarios</a>
<br/>
<a href="http://twitter.com/share?url=http://llops.com/blog/2008/07/27/enterframe-vs-timer-i/&text=Leyendo%20%22EnterFrame vs Timer (I)%22&via=llops%20blog">Compartir en Twitter</a> | 
<a href="http://www.facebook.com/sharer.php?u=http://llops.com/blog/2008/07/27/enterframe-vs-timer-i/&t=EnterFrame vs Timer (I)">Compartir en Facebook</a>

<br/><br/>
© <a href="http://llops.com/blog">llops blog</a> 2008 
</small></p>]]></content:encoded>
			<wfw:commentRss>http://llops.com/blog/2008/07/27/enterframe-vs-timer-i/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>El sistema de renderizado de Flash Player</title>
		<link>http://llops.com/blog/2008/05/24/el-sistema-de-renderizado-de-flash-player/</link>
		<comments>http://llops.com/blog/2008/05/24/el-sistema-de-renderizado-de-flash-player/#comments</comments>
		<pubDate>Sat, 24 May 2008 15:56:03 +0000</pubDate>
		<dc:creator>llops</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[enterFrame]]></category>
		<category><![CDATA[Error #1502]]></category>
		<category><![CDATA[Flash Player]]></category>
		<category><![CDATA[framerate]]></category>
		<category><![CDATA[redraw region]]></category>
		<category><![CDATA[render]]></category>
		<category><![CDATA[updateAfterEvent]]></category>

		<guid isPermaLink="false">http://llops.com/blog/2008/05/24/el-sistema-de-renderizado-de-flash-player/</guid>
		<description><![CDATA[Renderizar es el proceso de generar en pantalla una imagen a partir de unos datos. El responsable de representar por pantalla todo lo que sucede en una película Flash, tanto en el escenario como en el código, es el sistema de renderizado del runtime. Debido a que ActionScript es un lenguaje 100% visual, tener un [...]]]></description>
			<content:encoded><![CDATA[<p>Renderizar es el proceso de generar en pantalla una imagen a partir de unos datos. El responsable de representar por pantalla todo lo que sucede en una película Flash, tanto en el escenario como en el código, es el sistema de renderizado del runtime.</p>
<p>Debido a que ActionScript es un lenguaje 100% visual, tener un conocimiento profundo de este proceso nos ayudará a la hora de escribir y optimizar nuestro código, y evitará que cometamos errores normalmente difíciles de detectar.</p>
<p>En este artículo veremos cómo funciona.</p>
<p><span id="more-31"></span></p>
<h4>El sistema de renderizado del Flash Player</h4>
<p>El sistema de actualización de pantalla de Flash Player es <strong>automatizado</strong> y no hay forma de controlarlo.</p>
<p>Su funcionamiento interno está estrechamente ligado a la línea de tiempo de una película: se alcanza un frame, se ejecuta su código y se procesa la imagen. Incluso películas generadas sólo con código, sin ningún frame, o películas compiladas en Flex, que no cuenta con linea de tiempo, <strong>están gobernadas por el mismo mecanismo</strong>. A efectos del <em>runtime</em> de Flash, ejecuta cada película como si tuviera una linea de tiempo infinita.</p>
<p>El periodo de tiempo para visualizar cada frame viene marcado por el <em>framerate</em> del <em>swf</em>, que se mide en frames por segundo (fps).</p>
<p>Para hacernos mejor una idea, vamos a crear una serie de casos y a apoyar la explicación con gráficos y ejemplos.</p>
<h4>Caso 1</h4>
<p>Empecemos con una película con el framerate a 1 segundo, con código en el primer fotograma que crea contenido gráfico. Supongamos que Flash Player tarda 200 milisegundos en procesar el código, y que tarda 200 milisegundos más en hacer una actualización de la pantalla. El proceso sería el siguiente:</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/may08/render1.jpg" alt="" /></p>
<p class="img-comment">Procesamiento de 1 frame a 1 fps</p>
<p>Así pues, la cabeza lectora alcanza el primer fotograma y empieza a ejecutar el código. Una vez que ha acabado la pantalla no se actualiza inmediatamente, ya que el refresco viene determinado por el framerate, que está puesto a un segundo. Se entra en un tiempo de espera. Cuando se cumple el ciclo del framerate se procede a actualizar la pantalla, acción que tampoco es inmediata. Una vez que el Flash Player ha conseguido dibujar todo el contenido por pantalla, salta a un nuevo frame y vuelve a empezar el proceso.</p>
<h4>Caso 2</h4>
<p>Ahora imaginemos que la porción de código del frame es considerable y el programa tarda 1500ms en realizar dicha ejecución. ¿Qué sucede cuando se cumple el ciclo del framerate y no se ha procesado todo el código? Pues que el renderizado no se efectuará, se pondrá a la cola hasta que el código haya sido procesado.</p>
<p>El <em>runtime</em> de Flash <strong>nunca interrumpe la ejecución de código para actualizar la pantalla</strong>.</p>
<p>Podemos demostrarlo con un sencillo ejemplo. Tenemos una película con 5 frames y un framerate de 1 segundo. El quinto fotograma tiene un script que, en función de si está o no activo el checkbox, genera un bucle 9 mil millones de veces con el único objetivo de ralentizar el procesador.</p>
<div class="linea-extra"></div>
<p>
<object width="200" height="80">
<param name="movie" value="/blog/content/articulos/may08/caso2.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="200" height="80" src="/blog/content/articulos/may08/caso2.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/may08/caso2.zip" target="_blank">Descargar ejemplo</a></p>
<p>Si el checkbox está activado al entrar en el frame 5, Flash Player comienza a ejecutar código que no puede procesar antes del ciclo del framerate, por lo que la pantalla no se actualiza y vemos durante más tiempo el número "4".</p>
<blockquote><p><strong>Nota</strong>: cada swf tiene un tiempo máximo para ejecutar un script. Si se supera, aparece el famoso mensaje de "<em>Un script de esta película está provocando que el Reproductor de Flash se ejecute lentamente</em>".</p>
<p>En AS3 está documentado como el error #1502: "<em>El tiempo de ejecución del script ha superado el tiempo de espera predeterminado de 15 segundos</em>".<br />
El valor del tiempo se puede configurar en las propiedades de publicación.</p></blockquote>
<h4>Caso 3</h4>
<p>Pasemos ahora a una película con un sólo frame (hay que recordar que aunque sólo haya un frame o esté pausado, a efectos del <em>runtime</em> es como si hubiera una linea de tiempo infinita). En este frame se añade un <em>listener</em> al <em>stage</em> para escuchar un evento <em>MouseEvent</em>.<em>CLICK</em>, y con cada click se pinta una redonda en la posición del puntero. El framerate del swf está puesto a 0.4 (dos segundos y medio). Es notable la diferencia de tiempo desde que se ejecuta el código hasta que se dibujan las redondas en pantalla.</p>
<div class="linea-extra"></div>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/may08/caso3.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/may08/caso3.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/may08/caso3.zip" target="_blank">Descargar ejemplo</a></p>
<p>Si pensamos en el gráfico del "caso 1" sabemos que el código que registra el <em>listener</em> se ejecuta al principio, y que a cada ciclo se renderiza la pantalla. Pero... ¿cuándo se ejecuta el código asociado al evento click? Veamos otro gráfico más detallado.</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/may08/render2.jpg" alt="" /></p>
<p class="img-comment">Procesamiento de 1 frame a 1 fps</p>
<p>Cuando se entra en "Tiempo de espera", <strong>cualquier código generado como resultado de un evento</strong> (de mouse, de teclado, de un <em>Loader</em>, ...)  <strong>se ejecuta en este periodo y se muestra en pantalla en el siguiente ciclo</strong>.</p>
<p>Debido al exagerado framerate utilizado en este ejemplo, en cada frame se puede generar varias veces código para pintar los puntos, y en "Tiempo de renderizado" se actualizan todas a la vez.</p>
<h4>Caso 4</h4>
<p>Añadamos un simple botón al ejemplo anterior. Probemos a hacer algunos clicks para dibujar puntos y acto seguido <em>rollover</em> sobre el botón.</p>
<div class="linea-extra"></div>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/may08/caso4.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/may08/caso4.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/may08/caso4.zip" target="_blank">Descargar ejemplo</a></p>
<p>Curiosamente, al hacer rollover se dibujan inmediatamente los puntos, aunque no hayan pasado los 2'5 segundos del framerate. Esto es así porque <strong>ciertos eventos pueden forzar al Flash Player a renderizar la pantalla</strong>. Como en este caso, cada vez que se interactúa con un botón se indica al runtime que debe actualizar la pantalla para reflejar el cambio de estado del mismo. Esta actualización no afecta únicamente al objeto, sino a todos los que están esperando para ser procesados.</p>
<p>Al margen de los botones, acciones como pasar el puntero sobre un Sprite o usar el tabulador entre cajas de texto también fuerzan a renderizar.</p>
<p>Y aún hay más, porque mediante el método <em>updateAfterEvent</em>, que muchos recordaréis de versiones anteriores de <em>ActionScript</em>, podemos indicar al Player que actualice la pantalla. En AS3 se puede invocar en las siguientes clases: <em>MouseEvent</em>, <em>KeyboardEvent</em> y <em>TimerEvent</em>.</p>
<p>En el ejemplo anterior, sin modificar el framerate, añadamos un <em>updateAfterEvent</em> al evento click y veremos como se pintan los puntos sin demora.</p>
<div class="linea-extra"></div>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/may08/caso3_1.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/may08/caso3_1.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/may08/caso3_1.zip" target="_blank">Descargar ejemplo</a></p>
<p>Así pues, podemos hablar de <strong>dos categorías</strong> a la hora de renderizar:</p>
<ul>
<li>La que se genera a <strong>intervalos regulados por el framerate</strong></li>
<li>La que se genera <strong>bajo demanda de ciertos eventos</strong></li>
</ul>
<p>Al principio del artículo comentaba que el sistema de actualización de pantalla de Flash Player era automatizado. El hecho de poder usar <em>updateAfterEvent</em> no cambia nada, ya que realmente este método no actualiza la pantalla directamente, sólo indica al runtime la necesidad de hacerlo. Sin en el momento de la petición se encontrara ejecutando código no lo interrumpiría.<br />
Es importante recordar que el renderizado siempre está gobernado internamente.</p>
<h4>Caso 5</h4>
<p>Veamos ahora un último ejemplo para entender como encaja el evento e<em>nterFrame</em> en este rompecabezas.</p>
<p>En AS3 se puede definir un evento <em>enterFrame</em> en cualquier objeto del tipo <em>display object</em> (se encuentre o no en la <em>displayList</em>) y obviamente está sincronizado con el framerate de la película. Una vez definido, este evento <strong>se dispara cuando la cabeza lectora alcanza un nuevo fotograma</strong>, y lo hace antes de ejecutar cualquier código.</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/may08/render3.jpg" alt="" /></p>
<p class="img-comment">Procesamiento de 1 frame a 1 fps con un evento EnterFrame</p>
<p>Así pues, se alcanza un nuevo frame, se dispara un <em>Event.ENTER_FRAME</em> y se ejecuta el código asociado, acto seguido se ejecuta el código del frame y finalmente se entra en tiempo de espera hasta el siguiente renderizado.</p>
<p>Es importante notar que una vez que se dispara un <em>Event.ENTER_FRAME</em> lo hace <strong>a todos los objetos que están suscritos</strong>, aunque estén en diferentes líneas de tiempo, y se ejecuta siempre el código asociado <strong>de todos</strong> antes que el código del frame.</p>
<p>Para ejemplificar lo comentado, dejo un fla que define varios <em>enterFrame</em> en diferentes momentos y con código en cada frame. En la ventana de <em>output</em> se puede ver el orden de ejecución.</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/may08/caso5.zip" target="_blank">Descargar ejemplo</a></p>
<h4>Comprobación de renderizado</h4>
<p>En los gráficos que hemos visto, una vez pasado el "tiempo de espera" se entraba directamente en el "tiempo de renderizado". Esto no es exactamente así.</p>
<p>Al finalizar el tiempo de espera se evalúa si ha habido cambios "visuales" desde el último frame. Si hay nuevos datos que dibujar o modificar, se procede a actualizar la pantalla, pero si el contenido del último frame y del actual son visualmente idénticos no se entra en "tiempo de renderizado". De esta manera, el runtime evita hacer operaciones innecesarias.</p>
<p>Además, Flash Player sólo renderiza las zonas sensibles al cambio, no hace un update de toda la pantalla. Al conjunto de las zonas que hay que pintar se le llama "regiones de dibujo", conocido en inglés como "<em>redraw region"</em>. Si miramos en el menú contextual cuando ejecutamos una película en el IDE (o en una versión debug), veremos la siguiente opción:</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/may08/menu_contextual.jpg" alt="" /><img class="centered" src="http://llops.com/blog/content/articulos/may08/redraw_region.jpg" alt="" width="301" height="151" /></p>
<p>y al activarla encontraremos una serie de rectángulo rojos, que son las zonas que el Flash Player ha dibujado en el último render.</p>
<h4>Framerate real</h4>
<p>Durante todo el artículo hemos dicho varias veces que el framerate marca los ciclos en los que hay que actualizar la pantalla. Aunque esto es verdad, <strong>el framerate que le indicamos a nuestra película no suele alcanzarse la mayoría de veces</strong>, ya que en función de factores internos (la complejidad del código a ejecutar) y externos (la potencia de la máquina en la que se ejecuta Flash), el número de frames por segundo será menor al indicado. <strong>La cantidad de frames que es capaz de procesar el Flash Player en un segundo se conoce como framerate real</strong>.</p>
<p>Para mis experimentos utilizo una <a title="Clase FPS" href="http://llops.com/clases/as3/com/llops/utils/FPS.as" target="_blank">clase</a> muy simple que cuenta los frames reales que se procesan en un segundo y los muestra por pantalla. Un ejemplo de su uso:</p>
<div class="linea-extra"></div>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/may08/framerate_real.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/may08/framerate_real.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/may08/framerate_real.zip" target="_blank">Descargar ejemplo</a></p>
<p>El ejemplo está puesto a 31 fps. Lo primero que hay que tener en cuenta es que por el hecho de correr una película en un navegador ya pierde 4 o 5 frames. A medida que vayamos pintando el framerate real cada vez irá bajando más y más, debido a la carga de procesamiento. Hay que advertir que si dejamos de interactuar, el framerate se recupera aproximadamente a los valores iniciales, ya que en ese momento no se procesa código y debido a que no hay cambios visuales el Flash Player no pasa por el proceso de renderizado.</p>
<blockquote><p><strong>Nota</strong>: la clase FPS da un valor <strong>aproximado</strong> de la cantidad de fps. Se debe utilizar únicamente para depurar ya que no limpia sus recursos.</p></blockquote>
<p>Para acabar, veamos un resumen con todos los puntos claves del artículo.</p>
<h4>Resumiendo</h4>
<p>Flash Player cuenta con un sistema basado en frames para procesar código, y éste se combina con un motor de renderizado para dibujar los gráficos en pantalla.</p>
<p>La frecuencia de dicho procesamiento viene marcada por el framerate del swf.</p>
<p>El proceso de renderizado es automatizado.</p>
<p>Flash Player nunca interrumpe la ejecución de código para actualizar la pantalla.</p>
<p>Hay dos tipos de situaciones que desencadenan el renderizado: la que se genera a intervalos regulares marcados por el framerate y la que se genera tras la petición de ciertos eventos.</p>
<p>Cada vez que se alcanza un frame se sigue este proceso:</p>
<ul>
<li>Se dispara un evento ENTER_FRAME en caso de estar definido.</li>
<li>Se ejecuta en código asociado al enterFrame.</li>
<li>Se ejecuta el código del frame actual.</li>
<li>Se entra en un modo de espera hasta que toque renderizar la pantalla.</li>
<li>Si durante la ejecución de código anterior se ha definido eventos, se recogen y procesan en este tiempo de espera.</li>
<li>Una vez cumplido el ciclo del framerate se procede a una comprobación: si ha habido cambios gráficos se renderiza, sino, se salta al siguiente frame.</li>
</ul>
<p>Una vez iniciada una película, el Flash Player la trata como si tuviera una linea de tiempo infinita, no se deja de ejecutar hasta que se descarga.</p>
<p>El framerate asignado a una película no suele cumplirse, siempre suele ser menor debido a factores como la cantidad de código a ejecutar, la complejidad de éste, la potencia del ordenador, los recursos del sistema operativo, etc.</p>
<hr />
<p><small>
<a href="http://llops.com/blog/2008/05/24/el-sistema-de-renderizado-de-flash-player/#comments">17 comentarios</a>
<br/>
<a href="http://twitter.com/share?url=http://llops.com/blog/2008/05/24/el-sistema-de-renderizado-de-flash-player/&text=Leyendo%20%22El sistema de renderizado de Flash Player%22&via=llops%20blog">Compartir en Twitter</a> | 
<a href="http://www.facebook.com/sharer.php?u=http://llops.com/blog/2008/05/24/el-sistema-de-renderizado-de-flash-player/&t=El sistema de renderizado de Flash Player">Compartir en Facebook</a>

<br/><br/>
© <a href="http://llops.com/blog">llops blog</a> 2008 
</small></p>]]></content:encoded>
			<wfw:commentRss>http://llops.com/blog/2008/05/24/el-sistema-de-renderizado-de-flash-player/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Adobe AIR para clientes y abuelas</title>
		<link>http://llops.com/blog/2008/03/13/adobe-air-para-clientes-y-abuelas/</link>
		<comments>http://llops.com/blog/2008/03/13/adobe-air-para-clientes-y-abuelas/#comments</comments>
		<pubDate>Thu, 13 Mar 2008 00:17:33 +0000</pubDate>
		<dc:creator>llops</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[air]]></category>

		<guid isPermaLink="false">http://llops.com/blog/2008/03/13/adobe-air-para-clientes-y-abuelas/</guid>
		<description><![CDATA[Hace menos de un mes que Adobe ha lanzado oficialmente AIR y todo el mundo se ha hecho eco de la noticia (incluso diarios como El País). Con 2 años de desarrollo a las espaldas y 3 versiones Beta, cualquier persona que se mueva en el mundillo web sabe de que va el tema. Sin [...]]]></description>
			<content:encoded><![CDATA[<p>Hace menos de un mes que Adobe ha lanzado oficialmente <a href="http://www.adobe.com/products/air/" target="_blank">AIR</a> y <a href="http://www.google.es/search?hl=es&amp;client=firefox-a&amp;rls=org.mozilla%3Aes-ES%3Aofficial&amp;q=adobe+lanza+air&amp;btnG=Buscar&amp;meta=" target="_blank">todo el mundo</a> se ha hecho eco de la noticia (incluso diarios como <a href="http://www.elpais.com/articulo/internet/Adobe/acerca/aplicaciones/web/escritorio/elpeputec/20080225elpepunet_4/Tes" target="_blank">El País</a>).</p>
<p>Con 2 años de desarrollo a las espaldas y 3 versiones Beta, cualquier persona que se mueva en el mundillo web sabe de que va el tema. Sin embargo, AIR no afectará sólo a los desarrolladores, sino que va a suponer también un gran impacto en los usuarios.</p>
<p>Si has estado de viaje en otro planeta, esperas que tu cliente entienda porqué necesita invertir en AIR, o quieres que tu abuela no se sienta desplazada en las comidas, este artículo es para ti.</p>
<p><img src="http://llops.com/blog/content/articulos/mar08/logo_air.jpg" alt="" /></p>
<p><span id="more-27"></span></p>
<h4>¿Qué es AIR?</h4>
<p><strong>AIR</strong> son las siglas de <strong>Adobe Integrated Runtime</strong>, un entorno que permite ejecutar las aplicaciones AIR.</p>
<p>Cuando hablamos de una aplicación AIR hablamos de un programa de escritorio, igual que Windows Media Player, Photoshop o WinZip. Son programas que te descargas, instalas y ejecutas directamente sobre el sistema operativo.</p>
<p>AIR se construye sobre el Flash Player.</p>
<h4>¿Cómo funciona AIR?</h4>
<p>Para establecer una analogía, pensemos en una película Flash (.swf), que para verla es necesario tener instalado el Flash Player, o un archivo Word (.doc), que para abrirlo es necesario tener instalado Microsoft Word. Adobe AIR funciona igual: necesitas instalarlo primero para poder ejecutar sus aplicaciones.</p>
<p>AIR se instala como un programa más en nuestro ordenador, y actúa como una capa entre el sistema operativo y la aplicación que queremos instalar (representada por un paquete con extensión .air).</p>
<p>Las aplicaciones son multiplataforma, por lo que una única versión funcionará igual en todos los sistemas.</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/mar08/esquema_aplicaciones_air.jpg" alt="" /></p>
<p>Actualmente hay versiones de AIR para Windows y Mac, y se espera para finales de año la versión de Linux.</p>
<p>Adobe AIR es gratuito y se puede descargar en <a title="http://get.adobe.com/air/" href="http://get.adobe.com/air/">http://get.adobe.com/air/</a><br />
Una vez descargado, basta con ejecutar, aceptar la política de uso y en unos segundos lo tendremos instalado.</p>
<blockquote><p>Es importante notar que AIR no se encuentra con el resto de programas ya que no se puede ejecutar (únicamente es un contenedor para las aplicaciones AIR). Sin embargo, a nivel de instalación/desinstalación funciona como cualquier otro programa.</p></blockquote>
<h4>¿Cómo se instalan las aplicaciones AIR?</h4>
<p>Una vez que tenemos instalado AIR, instalar una aplicación es tan fácil como descargar, ejecutar y aceptar un par de cuadros de dialogo.</p>
<p>Uno de los cuadros que pueden llamar la atención es este:</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/mar08/aol_installer2.jpg" alt="" /></p>
<p>Hay que tener en cuenta que las aplicaciones de escritorio pueden comprometer la estabilidad del sistema, ya que acceden a ficheros del ordenador, se conectan a internet, etc. Es por eso que Adobe ha incluido esta pantalla de advertencia, que contiene información del creador de la aplicación y nos indica el estado de dos opciones que determinan el nivel de confianza:</p>
<ul>
<li><span style="text-decoration: underline;">Publisher Identity</span>, o identidad del creador. Para validar esta opción, Adobe obliga a que la aplicación posea un certificado digital, que se consigue mediante empresas especializadas que hacen una auditoría del programa.</li>
<li><span style="text-decoration: underline;">System Access</span>, o sistema de acceso. Relativo al nivel de acceso sobre el sistema de ficheros y a internet.</li>
</ul>
<p>No es necesario tener validadas estas dos opciones para instalar un programa, es más, la segunda opción suele aparecer siempre como "Unrestricted". Además, conseguir un certificado no es barato, con lo que muchos particulares no firmarán sus desarrollos. Simplemente es una medida de concienciación para no instalar programas cuya fuente sea desconocida.</p>
<p>Una vez que tenemos nuestra aplicación AIR la podemos ejecutar como cualquier otra.</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/mar08/aol_app.jpg" alt="" /></p>
<p class="img-comment">Nótese la pestaña de programa e incluso su icono en el <em>systray</em>.</p>
<p>Un buen sitio para empezar a descubrir programas es el <a title="Adobe Exchange" href="http://www.adobe.com/cfusion/exchange/index.cfm?event=productHome&amp;exc=24&amp;loc=en_us" target="_blank">Adobe Exchange</a>.</p>
<h4>¿Qué ventajas tiene AIR?</h4>
<ul>
<li>Es multiplataforma. Los desarrolladores sólo se preocupan de programar una versión que funcionará igual en todos los sistemas, que se traduce en llegar a más gente en menor tiempo y con menor coste.</li>
<li>Admite múltiples entornos para desarrollo: Ajax, HTML, Flex y Flash. Cualquier cosa que se pueda hacer en la web, se puede hacer en el escritorio.</li>
<li>La interfaz es completamente personalizable, aunque también puede adoptar el estilo de las ventanas del sistema operativo.</li>
<li>Es gratuito.</li>
</ul>
<h4>¿Por qué AIR?</h4>
<p>Durante los últimos 10 años hemos asistido al crecimiento imparable de Internet. A medida que Internet llegaba a más lugares y a más gente, se iban popularizando las aplicaciones web: sistemas informáticos que se encuentran en servidores web y que se acceden normalmente por medio de navegadores como Firefox o IExplorer. Aplicaciones como el webmail, los blogs, Flickr o Youtube son hoy nuestro pan de cada día.</p>
<p>Pero actualmente estamos asistiendo a una nueva corriente que propone un modelo mixto: tener las aplicaciones en el escritorio y que éstas aprovechen lo mejor de la web.</p>
<p>Quizá el caso que mejor ejemplifica este modelo sea el cliente de correo. Todos tenemos una cuenta de gmail, hotmail, yahoo, etc. que consultamos vía web, pero para trabajar solemos tener configurado un cliente como Outlook o Thunderbird. Por comodidad y rapidez utilizamos un aplicación de escritorio, y accedemos a Internet puntualmente (para recibir y enviar el correo).</p>
<p>Otras ejemplo podría ser Microsoft Messenger que, a pesar de tener una versión web, el 99% de la gente utiliza como aplicación de escritorio.</p>
<p>Si nos ponemos a pensar en el software que tenemos en nuestro ordenador nos daremos cuenta de la cantidad de programas que siguen este paradigma: antivirus, clientes FTP, reproductores, clientes P2P... algunos utilizando Internet como base y otros puntualmente.</p>
<p>Esto es lo que proponer Adobe mediante AIR: <strong>llevar las aplicaciones web al escritorio</strong>.</p>
<h4>¿Por qué ahora?</h4>
<p>La idea no es nueva: Macromedia tenía en mente esta situación desde el 2001, pero por aquella época había problemas insalvables como el rendimiento de las aplicaciones, la falta de potencia de los lenguajes, inconsistencia de los navegadores...  y por si esto fuera poco, la crisis del puntocom acabó de paralizar todo.</p>
<p>Así que siguieron trabajando esperando una nueva época. Ésta se vio reflejada con la llegada de la Web 2.0 y la revolución que supuso. En este momento, Adobe ya contaba con el Flash Player 9 y ActionScript 3.0, con el enorme salto de calidad que suponía.</p>
<p>Ahora sí, ha llegado el momento de saltar al escritorio.</p>
<h4>¿Es AIR el futuro?</h4>
<p>Una persona estrechamente relacionada con Adobe me comentó hace un año una cosa que me costó bastante de creer: la razón principal por la que Adobe adquirió Macromedia fue el interés que tenía por hacerse con Apollo (nombre anterior de AIR). Teniendo Macromedia la gallina de los huevos de oro, léase Flash, y otros programas líderes como Dreamweaver y Flex, etc. cuesta creer que su gran objetivo fuera este.</p>
<p>Otro dato a tener en cuenta son los movimientos del resto de compañías que, con algunas diferencias, también se embarcan en la lucha por el escritorio y por las RIAs (Rich Internet Application):</p>
<ul>
<li>Microsoft con su <a href="http://silverlight.net/default.aspx" target="_blank">SilverLight</a></li>
<li>Mozilla con <a href="http://labs.mozilla.com/2007/10/prism/" target="_blank">Prism</a></li>
<li>Google con <a href="http://gears.google.com/" target="_blank">Gears</a></li>
<li>Java con <a href="http://www.sun.com/software/javafx/index.jsp" target="_blank">JavaFX</a></li>
</ul>
<p>Está claro que el futuro de las aplicaciones tiene una linea marcada, y ahora sólo queda ver quién jugará mejor las cartas. AIR, sin duda, ya cuenta con un par de ases en la manga.</p>
<hr />
<p><small>
<a href="http://llops.com/blog/2008/03/13/adobe-air-para-clientes-y-abuelas/#comments">19 comentarios</a>
<br/>
<a href="http://twitter.com/share?url=http://llops.com/blog/2008/03/13/adobe-air-para-clientes-y-abuelas/&text=Leyendo%20%22Adobe AIR para clientes y abuelas%22&via=llops%20blog">Compartir en Twitter</a> | 
<a href="http://www.facebook.com/sharer.php?u=http://llops.com/blog/2008/03/13/adobe-air-para-clientes-y-abuelas/&t=Adobe AIR para clientes y abuelas">Compartir en Facebook</a>

<br/><br/>
© <a href="http://llops.com/blog">llops blog</a> 2008 
</small></p>]]></content:encoded>
			<wfw:commentRss>http://llops.com/blog/2008/03/13/adobe-air-para-clientes-y-abuelas/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Jugando con pixels (III)</title>
		<link>http://llops.com/blog/2008/02/14/jugando-con-pixels-iii/</link>
		<comments>http://llops.com/blog/2008/02/14/jugando-con-pixels-iii/#comments</comments>
		<pubDate>Thu, 14 Feb 2008 02:16:31 +0000</pubDate>
		<dc:creator>llops</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[bitmap]]></category>
		<category><![CDATA[bitmapData]]></category>
		<category><![CDATA[blendMode]]></category>
		<category><![CDATA[colorTransform]]></category>
		<category><![CDATA[fade]]></category>
		<category><![CDATA[glow]]></category>
		<category><![CDATA[particles]]></category>
		<category><![CDATA[pixel]]></category>

		<guid isPermaLink="false">http://llops.com/blog/2008/02/14/jugando-con-pixels-iii/</guid>
		<description><![CDATA[Lo prometido es deuda, y aunque he tardado bastante, aquí está la tercera entrega de esta serie. Está llena de ejemplos, todos con el código fuente para descargar y comentando. Vamos a jugar!! Pintando pixels Existen varios métodos para trabajar con los pixels de un bitmapData, pero las operaciones básicas para manipular el valor de [...]]]></description>
			<content:encoded><![CDATA[<p>Lo prometido es deuda, y aunque he tardado bastante, aquí está la tercera entrega de esta serie. Está llena de ejemplos, todos con el código fuente para descargar y comentando.</p>
<p>Vamos a jugar!!</p>
<p><span id="more-23"></span></p>
<h4>Pintando pixels</h4>
<p>Existen varios métodos para trabajar con los pixels de un bitmapData, pero las operaciones básicas para manipular el valor de un pixel son: <strong>getPixel()</strong>, <strong>setPixel()</strong>, <strong>getPixel32()</strong> y <strong>setPixel32()</strong>.</p>
<p><em>GetPixel</em> y <em>getPixel32</em> se encargan de leer el valor de un pixel, con la diferencia de que el primero se utiliza en las imágenes opacas mientras que el segundo permite leer el canal alpha del pixel. De la misma forma, con <em>setPixel</em> establecemos el color de un pixel sin transparencia y con <em>setPixel32</em> el de uno que sí la soporte.</p>
<p>Si se utiliza getPixel o setPixel (versión de 24 bits) en un imagen que soporta transparencia, el canal alpha se establece en FF (totalmente opaco), y si se utiliza la versión de 32 bits en una imagen que no soporta canal alpha, el canal alpha se ignora.</p>
<p>La sintaxis de los métodos es muy simple: sólo hay que pasar las coordenadas del pixel y, en el caso que haya que pintarlo, un color:</p>
<div class="igBar"><span id="lactionscript3-41"><a href="#" onclick="javascript:showCodeTxt('actionscript3-41'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-41">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">function</span> getPixel<span style="color: #555;">&#40;</span>x:<span style="color: #000099;">int</span>, y:<span style="color: #000099;">int</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">uint</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">function</span> setPixel<span style="color: #555;">&#40;</span>x:<span style="color: #000099;">int</span>, y:<span style="color: #000099;">int</span>, color:<span style="color: #000099;">uint</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">function</span> getPixel32<span style="color: #555;">&#40;</span>x:<span style="color: #000099;">int</span>, y:<span style="color: #000099;">int</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">uint</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">function</span> setPixel32<span style="color: #555;">&#40;</span>x:<span style="color: #000099;">int</span>, y:<span style="color: #000099;">int</span>, color:<span style="color: #000099;">uint</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Vamos a ver algunos ejemplos.</p>
<blockquote><p><strong>Nota</strong>: no voy a poner el código entero para que el post no crezca demasiado, sólo las porciones más significativas. Los ejemplos se pueden descargar y el código fuente está comentado.</p></blockquote>
<h4>Ejemplo 1 (Paint)</h4>
<p>Un <em>Paint</em> muy sencillo para mostrar los métodos <em>getPixel</em> y <em>setPixel</em>. Selecciona un color de la paleta con un click y pinta sobre el canvas con otro click. Para ilustrar mejor lo que es establecer un pixel no se puede pintar de forma continua.</p>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/feb08/paint.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/feb08/paint.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/feb08/paint.zip" target="_blank">Descargar ejemplo</a></p>
<p>Para este ejemplo se crean dos bitmaps (con sus correspondientes bitmapData): uno para crear la paleta de colores y otro para poder pintar. Para crear cada uno de los colores de la paleta, se utiliza el método fillRect(), que sirve para rellenar de un color un rectángulo (como el bote de pintura). Ninguno de los bitmaps soporta el canal alpha, así que se utilizan colores de 24 bits. También recordar que la clase <em>bitmap</em> no puede recibir eventos, por lo que se crean 2 <em>sprite</em> como contenedores.<br />
El método para coger el color es:</p>
<div class="igBar"><span id="lactionscript3-42"><a href="#" onclick="javascript:showCodeTxt('actionscript3-42'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-42">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">function</span> cogerColor<span style="color: #555;">&#40;</span>e:<span style="color: #000099;">MouseEvent</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span> <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Cogemos la posicion del raton sobre el bitmap de colores</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #1518ff;">var</span> cx:<span style="color: #000099;">int</span> = _bmpColores.<span style="color: #555;">mouseX</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #1518ff;">var</span> cy:<span style="color: #000099;">int</span> = _bmpColores.<span style="color: #555;">mouseY</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Obtenemos el color y lo almacenamos</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; _color_temp = _bmpDataColores.<span style="color: #555;">getPixel</span><span style="color: #555;">&#40;</span>cx, cy<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>y el método para pintar:</p>
<div class="igBar"><span id="lactionscript3-43"><a href="#" onclick="javascript:showCodeTxt('actionscript3-43'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-43">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">function</span> pintarColor<span style="color: #555;">&#40;</span>e:<span style="color: #000099;">MouseEvent</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span> <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Cogemos la posicion del raton sobre el bitmap del canvas</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #1518ff;">var</span> cx:<span style="color: #000099;">int</span> = _bmpCanvas.<span style="color: #555;">mouseX</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #1518ff;">var</span> cy:<span style="color: #000099;">int</span> = _bmpCanvas.<span style="color: #555;">mouseY</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Pintamos el pixel del color almacenado</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; _bmpDataCanvas.<span style="color: #555;">setPixel</span><span style="color: #555;">&#40;</span>cx, cy, _color_temp<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Sencillo, ¿no?</p>
<h4>Ejemplo 2 (Spray)</h4>
<p>Otro ejemplo donde se puede pintar con una herramienta tipo spray:</p>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/feb08/spray.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/feb08/spray.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/feb08/spray.zip" target="_blank">Descargar ejemplo</a></p>
<p>Aunque ya hemos visto lo fácil que es pintar un pixel, si se hace de uno en uno es una tarea muy lenta, por eso se suele utilizar otros métodos como el de este ejemplo.</p>
<div class="igBar"><span id="lactionscript3-44"><a href="#" onclick="javascript:showCodeTxt('actionscript3-44'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-44">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">function</span> pintar<span style="color: #555;">&#40;</span>e:<span style="color: #000099;">Event</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Si se puede pintar...</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #1518ff;">if</span> <span style="color: #555;">&#40;</span>_pintar_activo<span style="color: #555;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Cogemos las coordenas del mouse</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #1518ff;">var</span> p_mouse:<span style="color: #000099;">Point</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">Point</span><span style="color: #555;">&#40;</span>_bmp.<span style="color: #555;">mouseX</span>, _bmp.<span style="color: #555;">mouseY</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #1518ff;">for</span> <span style="color: #555;">&#40;</span><span style="color: #1518ff;">var</span> i:<span style="color: #000099;">int</span> = <span style="color: #FF0000;color:#000099;">0</span>; i &lt;<span style="color: #FF0000;color:#000099;">25</span>; i++<span style="color: #555;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Cogemos un punto aleatorio</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #1518ff;">var</span> p:<span style="color: #000099;">Point</span> = Random.<span style="color: #555;">obtenerPuntoCirculo</span><span style="color: #555;">&#40;</span>p_mouse,<span style="color: #FF0000;color:#000099;">10</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Pintamos el pixel en la posicion obtenida</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; _bmpData.<span style="color: #555;">setPixel</span><span style="color: #555;">&#40;</span>p.<span style="color: #555;">x</span>, p.<span style="color: #555;">y</span>, 0xFFCC99<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>La función <em>pintar()</em> se ejecuta en un <em>enterFrame</em>. Si se puede pintar, cogemos las coordenadas del mouse y pintamos 25 pixels por frame, generando el efecto de spray. La variable que controla si se puede pintar (<em>_pintar_activo</em>) se pone a <em>true</em> cuando dejamos presionado el botón izquierdo del mouse y se pone a <em>false</em> al soltarlo.</p>
<blockquote><p>La clase <em>Random</em> es una clase propia que cuenta con varias utilidades para obtener números y puntos aleatorios. En este caso, el método <em>obtenerPuntoCirculo()</em> acepta un objeto de la clase <em>Point</em> y un radio, y devuelve otro <em>Point</em> que pertenece al área del círculo.</p></blockquote>
<p>Para limpiar el canvas se utiliza esta función:</p>
<div class="igBar"><span id="lactionscript3-45"><a href="#" onclick="javascript:showCodeTxt('actionscript3-45'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-45">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">function</span> limpiarCanvas<span style="color: #555;">&#40;</span>e:<span style="color: #000099;">MouseEvent</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span> <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_bmpData.<span style="color: #555;">fillRect</span><span style="color: #555;">&#40;</span>_bmpData.<span style="color: #555;">rect</span>, 0x6699CC<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Al pasar el parámetro <em>rect</em> del mismo <em>bitmapData</em>, se pinta toda la superficie del color pasado, borrando todos los pixels que se habían pintado antes.</p>
<h4>Ejemplo 3 (Linea)</h4>
<p>Y otro ejemplo muy simple para pintar una línea.</p>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/feb08/linea.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/feb08/linea.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/feb08/linea.zip" target="_blank">Descargar ejemplo</a></p>
<p>En este caso se crea un bitmap transparente de color negro, pero con el canal alpha muy bajo (0x11000000). Hay dos variables que controlan las posiciones en x e y. En cada ciclo del <em>enterFrame</em> se pinta un pixel y se aumenta la variable de x.</p>
<div class="igBar"><span id="lactionscript3-46"><a href="#" onclick="javascript:showCodeTxt('actionscript3-46'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-46">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">function</span> dibujar<span style="color: #555;">&#40;</span>e:<span style="color: #000099;">Event</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Pintamos un pixel utilizando un color de 32 bits, ya que el bmpData es transparente</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; _bmpDataCanvas.<span style="color: #555;">setPixel32</span><span style="color: #555;">&#40;</span>_posx, _posy, 0xFFFF0000<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Aumentamos la posicion de x</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; _posx++;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Al aumentar <em>_posx</em> en 1 pixel cada vez tenemos una línea continua, pero si lo hiciéramos en 2 o 3 píxeles tendríamos una linea punteada, por ejemplo.</p>
<h4>Controlando los pixels</h4>
<p>El problema de los ejemplos que hemos visto hasta ahora es que conseguimos pintar, pero no tenemos ningún control de nuestros pixels una vez que los pintamos. Al fin y al cabo, pintar es sólo coger un pixel de un <em>bitmapData</em> y cambiarlo de color, realmente no existe ningún objeto que podamos manipular. ¿Cómo hacer, por ejemplo, si queremos pintar de una forma irregular?</p>
<p>La clave para esto es crear un objeto realmente, así podemos manipularlo a nuestro antojo y cuando sea necesario, coger su posición (x,y) y pintar ahí un pixel.</p>
<p>Para ello nos creamos una nueva clase, <em>Pixel</em>. Nuestra clase Pixel no tiene porqué extender de nada, ya que sólo la vamos a utilizar como un objeto que movemos donde queremos, pero no necesitamos una representación visual de él. Una versión muy simple para pintar una linea, como en el ejemplo 3, podría ser así:</p>
<div class="igBar"><span id="lactionscript3-47"><a href="#" onclick="javascript:showCodeTxt('actionscript3-47'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-47">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">package</span> <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #1518ff;">public</span> <span style="color: #1518ff;">class</span> Pixel <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #1518ff;">public</span> <span style="color: #1518ff;">var</span> x:<span style="color: #000099;">Number</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #1518ff;">public</span> <span style="color: #1518ff;">var</span> y:<span style="color: #000099;">Number</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #1518ff;">public</span> <span style="color: #1518ff;">var</span> name:<span style="color: #000099;">String</span> = <span style="color: #555;">"pixel_"</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #1518ff;">public</span> <span style="color: #1518ff;">function</span> Pixel<span style="color: #555;">&#40;</span>num:<span style="color: #000099;">int</span>,posx:<span style="color: #000099;">Number</span>,posy:<span style="color: #000099;">Number</span><span style="color: #555;">&#41;</span> <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;x = posx;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;y = posy;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name += <span style="color: #000099;">String</span><span style="color: #555;">&#40;</span>num<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #1518ff;">public</span> <span style="color: #1518ff;">function</span> mover<span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span> <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x++;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Creamos un <em>Pixel</em> pasando una posición <em>x, y</em> (el <em>num</em> únicamente es para generar un nombre que podemos utilizar para identificarlos: pixel_0, pixel_1, etc). Cada vez que llamemos a su método <em>mover()</em> aumentamos la variable x en un pixel. Si luego accedemos a dicha variable (que es pública), podemos pintar un pixel en esa posición.</p>
<blockquote><p>Hay que tener en cuenta que <em>x</em> e <em>y</em> son variable de la clase, no son las variables <em>x</em> e <em>y</em> que se heredan de la clase <em>DisplayObject</em> y que indican las coordenadas de un clip en el escenario. Se podía utilizar cualquier nombre, como <em>posx</em> y <em>posy</em>.</p></blockquote>
<p>Vamos a ver un ejemplo donde se genera un movimiento algo más complicado. Se trata de crear un ángulo, darle una fuerza de salida al Pixel y aplicarle gravedad.</p>
<h4>Ejemplo 4 (Explosión)</h4>
<p>Con dicho movimiento, generamos una especie de explosión con cada click.</p>
<p>
<object width="300" height="250">
<param name="movie" value="/blog/content/articulos/feb08/explosion.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="250" src="/blog/content/articulos/feb08/explosion.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/feb08/explosion.zip" target="_blank">Descargar ejemplo</a></p>
<p>En este caso creamos un <em>bitmapData</em> completamente transparente, <em>new BitmapData(ANCHO, ALTO, true, 0)</em>. Al hacer click se crean 50 objetos Pixel, y <strong>se almacenan en un array</strong>.</p>
<div class="igBar"><span id="lactionscript3-48"><a href="#" onclick="javascript:showCodeTxt('actionscript3-48'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-48">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #F0F; font-style: italic;">// Crear 50 pixels y añadirlos al array</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">for</span> <span style="color: #555;">&#40;</span><span style="color: #1518ff;">var</span> i:<span style="color: #000099;">int</span> = <span style="color: #FF0000;color:#000099;">0</span>; i &lt;<span style="color: #FF0000;color:#000099;">50</span>; i++<span style="color: #555;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_pixels.<span style="color: #555;">unshift</span><span style="color: #555;">&#40;</span><span style="color: #1518ff;">new</span> Pixel<span style="color: #555;">&#40;</span>_cont, mouseX, mouseY<span style="color: #555;">&#41;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_cont++;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Hay que tener en cuenta que cuando se manipulan pixels se suele hacer con varios cientos o miles. La mejor forma es meterlos en un array, ya que es muy fácil recorrerlo después y aplicarles acciones, como en este caso:</p>
<div class="igBar"><span id="lactionscript3-49"><a href="#" onclick="javascript:showCodeTxt('actionscript3-49'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-49">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #F0F; font-style: italic;">// Recorremos el array de pixels</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">for</span> <span style="color: #555;">&#40;</span><span style="color: #1518ff;">var</span> a:<span style="color: #000099;">String</span> <span style="color: #1518ff;">in</span> _pixels<span style="color: #555;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Cogemos cada pixel</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #1518ff;">var</span> p:Pixel = _pixels<span style="color: #555;">&#91;</span>a<span style="color: #555;">&#93;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Movemos el pixel a su siguiente posicion</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; p.<span style="color: #555;">mover</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// Pintamos en el bitmap, en la posiciones</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #F0F; font-style: italic;">// de nuestro pixel</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; _bmpData.<span style="color: #555;">setPixel32</span><span style="color: #555;">&#40;</span>p.<span style="color: #555;">x</span>, p.<span style="color: #555;">y</span>, AMARILLO<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Con este mecanismo, ahora sí tenemos control sobre todos nuestros pixels. Además de moverlos individualmente, podemos saber cuándo están fuera de pantalla para limpiar recursos, o guardar otras propiedades en la clase <em>Pixel</em>, como un color individual para cada uno.</p>
<p>Como no hemos creado una variable de clase para cada pixel, la única referencia que existe se encuentra en el array. Para poder borrar un pixel sólo hemos de quitar su posición en el array, de esta manera se queda sin referencia y el recolector de basura se encargará de eliminarlo de la memoria (mirar el código fuente y los comentarios).</p>
<blockquote><p>La clase Pixel no está comentada, ya que sólo hay que entender que cuenta con unas variables que almacenan la posición. Explicar el movimiento angular no es el objetivo del ejemplo.</p></blockquote>
<h4>Fundiendo los pixels</h4>
<p>Por ahora llevamos un buen camino: sabemos cómo manipular los pixels individualmente, como crearlos almacenándolos en un array, como gestionarlos a la vez y cómo pintar el recorrido en nuestro <em>bitmapData</em>. El problema que nos encontramos es que a medida que vamos pintando más y más, nuestro <em>bitmapData</em> queda lleno de pixels y se vuelve inservible para cualquier propósito que no sea dibujar.</p>
<p>Una técnica muy vistosa es crear un fade en cada pixel, así lo vamos degradando hasta que sea invisible. Pero claro, nuestro pixel sólo es un puntito de color que no cuenta con una propiedad <em>alpha</em> como si fuera un <em>Sprite</em> o un <em>MovieClip</em>. La solución pasa por aplicar el fade a todo el bitmapData, mediante un objeto <em>ColorTransform</em> y su propiedad <em>alphaMultiplier</em>.</p>
<h4>Ejemplo 5 (Explosión Fade)</h4>
<p>Click para generar la explosión con fade.</p>
<p>
<object width="300" height="250">
<param name="movie" value="/blog/content/articulos/feb08/explosion_fade.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="250" src="/blog/content/articulos/feb08/explosion_fade.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/feb08/explosion_fade.zip" target="_blank">Descargar ejemplo</a></p>
<p>Usando esta técnica el ejemplo cambia por completo y gana bastantes enteros. Veamos el código añadido.</p>
<p>Primero creamos una variable de clase para el objeto ColorTransform:</p>
<div class="igBar"><span id="lactionscript3-50"><a href="#" onclick="javascript:showCodeTxt('actionscript3-50'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-50">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">var</span> _ct:<span style="color: #000099;">ColorTransform</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">ColorTransform</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>En el constructor indicamos la cantidad de alfa (de 0 a 1):</p>
<div class="igBar"><span id="lactionscript3-51"><a href="#" onclick="javascript:showCodeTxt('actionscript3-51'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-51">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_ct.<span style="color: #555;">alphaMultiplier</span> = .<span style="color: #FF0000;color:#000099;">9</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Por último, en nuestro enterFrame lo aplicamos:</p>
<div class="igBar"><span id="lactionscript3-52"><a href="#" onclick="javascript:showCodeTxt('actionscript3-52'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-52">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_bmpData.<span style="color: #000099;">colorTransform</span><span style="color: #555;">&#40;</span>_bmpData.<span style="color: #555;">rect</span>, _ct<span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Con esta última línea, lo que estamos haciendo es que en cada frame le damos a nuestro <em>bitmapData</em> una transparencia de 0.9, y al hacerlo de manera tan continuada acaba fundiendo lo que hemos dibujado. Por otro lado, como estamos continuamente pintando sobre nuestro bitmap siempre vemos algo en pantalla.</p>
<p>Si el valor de <em>alphaMultiplier</em> es bajo (por ejemplo, 0.7), apenas veremos nada, ya que el fundido se producirá demasiado rápido. Por el contrario, si nuestro valor se acerca a 1 (por ejemplo, 0.98), el objeto <em>ColorTransform</em> tardará demasiado en fundir la imagen.</p>
<p>Descárgate el ejemplo y prueba diferentes combinaciones entre el número de pixels que genera cada click, el valor de <em>alphaMultiplier</em> y el número de frames de la película para entender la relación entre los elementos.</p>
<blockquote><p><strong>Importante</strong>: para utilizar esta técnica el <em>bitmapData</em> debe tener la propiedad <em>transparent</em> a <em>true</em>, ya que si la imagen es opaca el fundido se verá reflejado sobre la misma.</p></blockquote>
<h4>Generando pixels indefinidamente</h4>
<p>En más de una ocasión nos interesará generar partículas continuamente sin que el usuario tenga que interactuar. Un ejemplo podría ser crear la estela de un cometa o simular los propulsores de un cohete, o simplemente para obtener un efecto visual.</p>
<p>La idea es tan simple como garantizar que siempre haya un número mínimo de pixels en pantalla: para ello debemos eliminar los que se encuentren fuera de los límites y generar nuevos.</p>
<p>Para que resulte más claro, vamos a trabajar sobre un ejemplo</p>
<blockquote><p><strong>Nota</strong>: para no consumir recursos innecesarios, los ejemplos de este tipo sólo funcionarán cuando el cursor esté dentro del swf.</p></blockquote>
<h4>Ejemplo 6 (Cascadas)</h4>
<p>Con las técnicas explicadas anteriormente, aquí tenemos una cascada de pixels. Al salir del área visible se generan nuevas partículas y el ciclo nunca se interrumpe.</p>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/feb08/cascadas.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/feb08/cascadas.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/feb08/cascadas.zip" target="_blank">Descargar ejemplo</a></p>
<p>Para ello añadimos dos nuevas variables de clase:</p>
<div class="igBar"><span id="lactionscript3-53"><a href="#" onclick="javascript:showCodeTxt('actionscript3-53'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-53">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">var</span> _max_pixels:<span style="color: #000099;">int</span> = <span style="color: #FF0000;color:#000099;">400</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">var</span> _pixels_por_frame:<span style="color: #000099;">int</span> = <span style="color: #FF0000;color:#000099;">20</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>La primera indica el número de pixels máximo que puede haber en pantalla, y la segunda el número de pixels por frame que se han de generar en caso que no se haya superado el número máximo.</p>
<p>Dichas variables se utilizan en el <em>enterFrame</em>:</p>
<div class="igBar"><span id="lactionscript3-54"><a href="#" onclick="javascript:showCodeTxt('actionscript3-54'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-54">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">if</span> <span style="color: #555;">&#40;</span>_pixels.<span style="color: #555;">length</span> &lt;= _max_pixels<span style="color: #555;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #1518ff;">for</span> <span style="color: #555;">&#40;</span><span style="color: #1518ff;">var</span> i:<span style="color: #000099;">int</span> = <span style="color: #FF0000;color:#000099;">0</span>; i &lt;_pixels_por_frame; i++<span style="color: #555;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp;&nbsp; &nbsp;<span style="color: #F0F; font-style: italic;">// Código para crear los pixels</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Miramos la longitud del <em>array</em>, y si es menor que el número de partículas, entramos en el bucle. En vez de crear una partícula por frame, este <em>for</em> nos permite generar un número elevado. Si no lo hiciéramos así, las partículas dependerían siempre del framerate de la película, y normalmente no podríamos conseguir muchas a la vez.</p>
<p>Por último, en el <em>enterFrame</em>, por cada pixel, se ejecuta este linea:</p>
<div class="igBar"><span id="lactionscript3-55"><a href="#" onclick="javascript:showCodeTxt('actionscript3-55'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-55">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">if</span> <span style="color: #555;">&#40;</span>p.<span style="color: #555;">y</span>&gt; ALTO<span style="color: #555;">&#41;</span> eliminarPixel<span style="color: #555;">&#40;</span>p<span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Es imprescindible comprobar continuamente la posición del pixel para poder eliminarlo y generar nuevos. Evidentemente, en función del tipo de experimento, habrá que comprobar otros límites para eliminarlo.</p>
<p>Nótese que el número de pixels máximo nunca es exacto, ya que si hemos fijado un valor de 400 y tenemos en pantalla 392, al entrar en el bucle nos generará 20 más teniendo un total de 412. Esto no es significativo ya que se eliminan y crean con mucha rapidez. Lo importante es tener un valor que nos sirva visualmente sin influir excesivamente en el rendimiento.</p>
<p>Nótese también que si el número de pixels máximo es muy elevado y el de los pixels por frame no lo es, nunca se alcanzará el máximo. En el código, al final de la función del <em>enterFrame</em>, hay un <em>trace</em> que indica la longitud del array. Es bueno ir mirándolo hasta conseguir ajustar las cantidades.</p>
<p>Por último, comentar que cuando se juegan con partículas es muy importante tener en cuenta el rendimiento, ya que es muy fácil colapsar la CPU a partir de ciertos valores. Por eso en mis experimentos siempre utilizo un medidor de frames por segundo, que es el recuadro azul que se ve en el ejemplo. Utilizándolo se puede comprobar si nuestra película está rindiendo a un nivel aceptable. Todos estos swf tiene un framerate de 31, y en navegador es frecuente que bajen hasta los 24-26. Recomiendo usar siempre uno para tareas de depuración (en general con cualquier desarrollo que consuma muchos procesos). La clase es <span style="text-decoration: underline;">FPS</span> y se encuentra en el paquete <span style="text-decoration: underline;">com.llops.utils</span>.</p>
<h4>Aplicando filtros: Glow</h4>
<p>Como siempre, los filtros nos permiten crear efectos visuales muy potentes. En el tema que nos ocupa, el que mejor casa con la programación pixel es el filtro <em>Glow</em>. Este filtro nos permite crear una pequeña aureola de cualquier color alrededor del pixel, y a la vez le podemos aplicar blur para suavizar los puntos. Se utiliza normalmente para generar brillos, y la intensidad aumenta al concentrar partículas en un mismo punto.</p>
<h4>Ejemplo 7 (Cascadas Glow)</h4>
<p>Nuestra cascada de antes era algo sosa, vamos a ver como queda con un simple <em>glow</em>.</p>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/feb08/cascadas_glow.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/feb08/cascadas_glow.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/feb08/cascadas_glow.zip" target="_blank">Descargar ejemplo</a></p>
<p>La diferencia con el ejemplo anterior es notable. Los pixels ya no son planos y el resultado es mucho más vistoso.</p>
<p>Los filtros se aplican sobre el bitmap directamente, en el formato de array. Lo único que hay que hacer es importar la clase <em>flash.filters.GlowFilter</em> y crear uno:</p>
<div class="igBar"><span id="lactionscript3-56"><a href="#" onclick="javascript:showCodeTxt('actionscript3-56'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-56">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> _glow:<span style="color: #000099;">GlowFilter</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">GlowFilter</span><span style="color: #555;">&#40;</span>_color_glow, <span style="color: #FF0000;color:#000099;">1</span>, <span style="color: #FF0000;color:#000099;">4</span>, <span style="color: #FF0000;color:#000099;">4</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_bmp.<span style="color: #555;">filters</span> = <span style="color: #555;">&#91;</span>_glow<span style="color: #555;">&#93;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Aunque tiene más parámetros, los 4 primeros son los principales. Con ellos indicamos el color, la transparencia, y el blur en <em>x</em> y en <em>y</em>.</p>
<blockquote><p><strong>Nota</strong>: no poner un blur mayor que 12, ya que tiende a desvanecerse y no se aprecia.</p></blockquote>
<p>Para ver los resultados con distintas combinaciones, en el código he puesto algunos colores y dos variables para el color interior y el del glow. Puedes hacer tus pruebas:</p>
<div class="igBar"><span id="lactionscript3-57"><a href="#" onclick="javascript:showCodeTxt('actionscript3-57'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-57">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">const</span> ROJO:<span style="color: #000099;">uint</span> = 0xFFFF0000;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">const</span> NEGRO:<span style="color: #000099;">uint</span> = 0xFF000000;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">const</span> BLANCO:<span style="color: #000099;">uint</span> = 0xFFFFFFFF;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">const</span> AZULADO:<span style="color: #000099;">uint</span> = 0xFF0099FF;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">const</span> AMARILLO:<span style="color: #000099;">uint</span> = 0xFFFFFF00;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">var</span> _color_pixel:<span style="color: #000099;">uint</span> = BLANCO</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">var</span> _color_glow:<span style="color: #000099;">uint</span> = AZULADO; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Y aquí va otro ejemplo, este con más intención:</p>
<h4>Ejemplo 8 (Lava)</h4>
<p>Simulación de un río de lava. Se rebaja la velocidad de los pixels para acumularlos y se aumenta el blur del glow.</p>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/feb08/lava.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/feb08/lava.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/feb08/lava.zip" target="_blank">Descargar ejemplo</a></p>
<p>Podríamos decir que da bastante el pego :)</p>
<h4>¿Todavía hay más?</h4>
<p>Pues aún queda un truquillo más que puede dar mucho juego: el parámetro <em>blendMode</em> de <em>DisplayObject</em>, que consta de 14 modos. El resultado final de cada modo depende mucho del color del bitmap, las capas adyacentes, etc., pero en general, algunos modos como ADD, DIFFERENCE o INVERT suelen ofrecer posibilidades interesantes. Considéralo un efecto avanzado que puede requerir bastantes pruebas hasta dar con un resultado convincente.</p>
<p>Basta con una sola línea para utilizarlo:</p>
<div class="igBar"><span id="lactionscript3-58"><a href="#" onclick="javascript:showCodeTxt('actionscript3-58'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-58">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_bmp.<span style="color: #000099;">blendMode</span> = <span style="color: #000099;">BlendMode</span>.<span style="color: #555;">ADD</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Y la verdad es que siempre habrá mucho más: se le pueden añadir filtros de desplazamiento, ruido, interacción con el usuario, generación aleatoria de color... en definitiva, un sinfín de posibilidades. Sólo hace falta tener ganas de experimentar.</p>
<h4>Y para acabar</h4>
<p>Todos los ejemplos que he puesto hasta ahora han tenido una finalidad didáctica, así que no han sido muy espectaculares. De todas maneras, para los exigentes, y sin meterme en código complejo, dejo un último experimento que personalmente me gusta mucho ;)</p>
<h4>Ejemplo 9 (Conexiones)</h4>
<p>Combina los métodos descritos: transparencia, fade, glow, blendMode...</p>
<p>
<object width="300" height="250">
<param name="movie" value="/blog/content/articulos/feb08/conexiones.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="250" src="/blog/content/articulos/feb08/conexiones.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/feb08/conexiones.zip" target="_blank">Descargar ejemplo</a></p>
<h4>Resumiendo</h4>
<p>AS3 es uno de los lenguajes (sino el que más) que permite exprimir al máximo el concepto de "programación creativa", y la programación orientada a pixel da buena prueba de ello.</p>
<p>En este tercer artículo he intentado poner algunas herramientas encima de la mesa, y ahora depende de cada uno utilizarlas a su manera. Soy un fan de este tipo de experimentos, así que si programas algo relacionado me encantará verlo :)</p>
<p>También me gustaría remarcar la idea que hasta ahora no hemos jugado con imagen, sino con bitmaps creados de cero, que son simples recuadros de color. Es fácil imaginar las posibilidades al añadir fotografía...</p>
<p>En cuanto a esto, decir que mi intención era escribir un par de artículos más sobre estos temas, pero he de reconocer que estoy un poco saturado de tanto pixel, y me apetece hacer cosas nuevas. Así que de momento, haré una pausa indefinida en esta serie. Espero que lo visto hasta ahora haya sido de interés.</p>
<hr />
<p><small>
<a href="http://llops.com/blog/2008/02/14/jugando-con-pixels-iii/#comments">11 comentarios</a>
<br/>
<a href="http://twitter.com/share?url=http://llops.com/blog/2008/02/14/jugando-con-pixels-iii/&text=Leyendo%20%22Jugando con pixels (III)%22&via=llops%20blog">Compartir en Twitter</a> | 
<a href="http://www.facebook.com/sharer.php?u=http://llops.com/blog/2008/02/14/jugando-con-pixels-iii/&t=Jugando con pixels (III)">Compartir en Facebook</a>

<br/><br/>
© <a href="http://llops.com/blog">llops blog</a> 2008 
</small></p>]]></content:encoded>
			<wfw:commentRss>http://llops.com/blog/2008/02/14/jugando-con-pixels-iii/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Jugando con pixels (II)</title>
		<link>http://llops.com/blog/2008/01/27/jugando-con-pixels-ii/</link>
		<comments>http://llops.com/blog/2008/01/27/jugando-con-pixels-ii/#comments</comments>
		<pubDate>Sun, 27 Jan 2008 02:07:56 +0000</pubDate>
		<dc:creator>llops</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[bitmap]]></category>
		<category><![CDATA[bitmapData]]></category>

		<guid isPermaLink="false">http://llops.com/blog/2008/01/27/jugando-con-pixels-ii/</guid>
		<description><![CDATA[Ahora que ya sabemos cómo funciona el color en un pixel, vamos a ver la clase clave para manipularlos: BitmapData, y por extensión, la clase Bitmap, ya que funcionan en conjunto. Nota: Sino leíste la primera parte de la serie, te recomiendo que le eches un vistazo antes de seguir. La clase BitmapData, como su [...]]]></description>
			<content:encoded><![CDATA[<p>Ahora que ya sabemos cómo funciona el color en un pixel, vamos a ver la clase clave para manipularlos: <em>BitmapData</em>, y por extensión, la clase <em>Bitmap</em>, ya que funcionan en conjunto.</p>
<blockquote><p><strong>Nota</strong>: Sino leíste la <a title="Jugando con pixels (I)" href="http://llops.com/blog/2008/01/20/jugando-con-pixels-i/" target="_blank">primera parte</a> de la serie, te recomiendo que le eches un vistazo antes de seguir.</p></blockquote>
<p><span id="more-19"></span></p>
<p>La clase <em>BitmapData</em>, como su nombre indica, <strong>representa los datos de un bitmap</strong>, o lo que es lo mismo, almacena todos los pixels de una imagen. Esta representación solamente existe en memoria. Por otro lado, la clase <strong><em>Bitmap</em> es un envoltorio para <em>BitmapData</em></strong>, y permite manipular la imagen como objeto visual.</p>
<p>Pero... ¿por qué utilizar dos clases? ¿No sería más fácil una única clase encargada de manipular la imagen? Tratemos este punto antes de seguir con la sintaxis.</p>
<h4>Arquitectura de BitmapData y Bitmap</h4>
<p>Aunque las dos clases se encuentran en el paquete <em>flash.display</em>, <em>BitmapData</em> no pertenece a la <em>Display List</em>. Si echamos un vistazo a las clases que conforman la lista de visualización, podemos comprobar que sólo <em>Bitmap</em> hereda de <em>DisplayObject</em>, y por tanto es la única que se puede representar en pantalla:</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/ene08/display_list.jpg" alt="" /></p>
<p>Gracias a esta separación, las operaciones que se realizan con los pixels de una imagen no entran en el motor de renderizado del Flash Player, evitando tener que redibujar constantemente el contenido, cosa que pasa con los vectores. En este concepto se basa la técnica de cachear a bitmap (cacheAsBitmap).</p>
<blockquote><p>Hasta la llegada de Flash8, un gran número de experimentos se veían frustrados por el bajo rendimiento del player cuando se dibujaban muchos vectores en pantalla. Estos problemas desaparecieron en el momento en que se pudieron agrupar estos vectores y pasarlos a una única imagen, liberando completamente al procesador de esta dura tarea.</p></blockquote>
<p>Y la otra gran ventaja de esta separación es que distintos objetos <em>Bitmap</em> pueden utilizar el mismo <em>BitmapData</em>. De esta manera, podríamos tener una representación rotada, otra escalada, etc. y sólo consumiría la memoria de una imagen.</p>
<p>Visto así, es una buena idea tener separadas ambas clases: una para manipular los datos de la imagen y otra para manipular el objeto en pantalla.</p>
<p>No está de más observar que <em>Bitmap</em> no hereda de <em>InteractiveObject</em>, con lo que no puede recibir eventos de teclado ni de ratón. Si queremos que esto sea así, deberemos reparentar nuestro objeto en un <em>Sprite</em> o <em>MovieClip</em>. Por otro lado, en caso de utilizar imágenes externas, deberemos cargarlas mediante un objeto <em>Loader</em>, que sí extiende <em>InteractiveObject</em>.</p>
<h4>Sintaxis de BitmapData y Bitmap</h4>
<p><em>BitmapData</em> permite crear una imagen de cero o manipular una existente.</p>
<blockquote><p><strong>Nota</strong>: de momento nos centraremos en las imágenes creadas por código, que son simples rectángulos de color. En otro capítulo veremos cómo cargar imágenes o utilizarlas desde la librería.</p></blockquote>
<p>La firma del constructor es:</p>
<div class="igBar"><span id="lactionscript3-64"><a href="#" onclick="javascript:showCodeTxt('actionscript3-64'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-64">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #000099;">BitmapData</span><span style="color: #555;">&#40;</span>width:<span style="color: #000099;">int</span>, height:<span style="color: #000099;">int</span>, transparent:<span style="color: #000099;">Boolean</span> = <span style="color: #000099;">true</span>, fillColor:<span style="color: #000099;">uint</span> = 0xFFFFFFFF<span style="color: #555;">&#41;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Los dos primeros parámetros especifican el ancho y alto que tendrá nuestro objeto. El tercer valor indica si la imagen soporta transparencia por pixel, es decir, si la imagen tendrá canal alfa. Por defecto tiene. El último corresponde al color de la imagen, por defecto blanca.</p>
<p>Es importante recordar los siguiente puntos:</p>
<ul>
<li>Una vez creada la imagen, no se pueden cambiar su anchura y altura</li>
<li>Si creamos la imagen opaca (transparent = false), el canal alfa del color será ignorado (por ejemplo, 0x55FFFFFF)</li>
<li>El Player renderiza más rápido las imágenes que no soportan transparencia, así que si no es necesaria, mejor forzar el parámetro a false.</li>
</ul>
<p>Así pues, para crear una imagen azul, opaca y de 100x100 pixels escribiríamos:</p>
<div class="igBar"><span id="lactionscript3-65"><a href="#" onclick="javascript:showCodeTxt('actionscript3-65'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-65">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">import</span> flash.<span style="color: #555;">display</span>.<span style="color: #000099;">BitmapData</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> bmpData:<span style="color: #000099;">BitmapData</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">BitmapData</span><span style="color: #555;">&#40;</span><span style="color: #FF0000;color:#000099;">100</span>, <span style="color: #FF0000;color:#000099;">100</span>, <span style="color: #000099;">false</span>, 0xFF0000FF<span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>En este punto, tenemos nuestra imagen creada, pero solo existe en memoria, no podemos representarla visualmente (aunque ya podemos manipular sus pixels, aplicarle filtros, etc). Para ello, debemos crear un objeto <em>Bitmap</em> que la contenga. Veamos su constructor:</p>
<div class="igBar"><span id="lactionscript3-66"><a href="#" onclick="javascript:showCodeTxt('actionscript3-66'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-66">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #000099;">Bitmap</span><span style="color: #555;">&#40;</span><span style="color: #000099;">bitmapData</span>:<span style="color: #000099;">BitmapData</span> = <span style="color: #000099;">null</span>, <span style="color: #000099;">pixelSnapping</span>:<span style="color: #000099;">String</span> = <span style="color: #555;">"auto"</span>, smoothing:<span style="color: #000099;">Boolean</span> = <span style="color: #000099;">false</span><span style="color: #555;">&#41;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>El primer parámetro que nos pide es un objeto <em>BitmapData</em>, así que pasándolo ya tenemos asociados los datos en memoria al contenedor (¿fácil, no?). El segundo y tercer argumento controlan el ajuste de pixel y el suavizado al escalarse. En la gran mayoría de los casos no son relevantes, así que nos olvidaremos de ellos.</p>
<p>Si añadimos algunas líneas más ya tendremos nuestra imagen en pantalla:</p>
<div class="igBar"><span id="lactionscript3-67"><a href="#" onclick="javascript:showCodeTxt('actionscript3-67'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-67">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">import</span> flash.<span style="color: #555;">display</span>.<span style="color: #000099;">BitmapData</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">import</span> flash.<span style="color: #555;">display</span>.<span style="color: #000099;">Bitmap</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> bmpData:<span style="color: #000099;">BitmapData</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">BitmapData</span><span style="color: #555;">&#40;</span><span style="color: #FF0000;color:#000099;">100</span>, <span style="color: #FF0000;color:#000099;">100</span>, <span style="color: #000099;">false</span>, 0xFF0000FF<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> bmp:<span style="color: #000099;">Bitmap</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">Bitmap</span><span style="color: #555;">&#40;</span>bmpData<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">addChild<span style="color: #555;">&#40;</span>bmp<span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>También es posible asociar el <em>BitmapData</em> al <em>Bitmap</em> mediante la propiedad <em>bitmapData</em> de este último:</p>
<div class="igBar"><span id="lactionscript3-68"><a href="#" onclick="javascript:showCodeTxt('actionscript3-68'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-68">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> bmpData:<span style="color: #000099;">BitmapData</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">BitmapData</span><span style="color: #555;">&#40;</span><span style="color: #FF0000;color:#000099;">100</span>, <span style="color: #FF0000;color:#000099;">100</span>, <span style="color: #000099;">false</span>, 0xFF0000FF<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> bmp:<span style="color: #000099;">Bitmap</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">Bitmap</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">bmp.<span style="color: #000099;">bitmapData</span> = bmpData;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">addChild<span style="color: #555;">&#40;</span>bmp<span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Aquí hay un pequeño ejemplo donde se crean cuatro bitmaps de 60x40 con distintos valores en la transparencia y color. Si tienes alguna duda en este punto, te aconsejo que descargues el ejemplo y pruebes distintas combinaciones.</p>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/ene08/creacion_bitmaps.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/ene08/creacion_bitmaps.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/ene08/creacion_bitmaps.zip" target="_blank">Descargar ejemplo</a></p>
<p>Hay que tener claro que los dos primeros valores hexadecimales determinan la transparencia, pero siempre que <em>transparent</em> sea <em>true</em>. Para crear una imagen completamente transparente se puede utilizar 0, que es lo mismo que 0x00000000.</p>
<h4>Limitaciones de los bitmaps: los 2880 pixels</h4>
<p>Si alguna vez has mirado alguna documentación o artículo sobre <em>BitmapData</em>, casi seguro que habrás visto una advertencia sobre que no se pueden crear imágenes con un ancho o alto superior a 2880 pixels. Esta limitación está puesta para que las películas no consuman excesiva memoria RAM, ya que una imagen de esas dimensiones consume aproximadamente 32 MB.</p>
<p>¿Y de dónde sale esta cantidad?</p>
<p>Pues como comentamos en el primer capítulo, un pixel tiene 4 bytes de información (1 byte por cada canal). Si tenemos una imagen de 2880x2880, tenemos 8.294.400 pixels, y al multiplicar por 4 tenemos que nuestra imagen consume una memoria de 33.177.600 bytes. Si lo dividimos entre 1024 (1KiloByte) tenemos 32.400 KB, y si lo volvemos a dividir entre 1024 tenemos 31'64 MB.</p>
<p>Personalmente, creo que los 2880 es una medida más que suficiente, y casi nunca necesitaremos una imagen de esas dimensiones. Aún así, hay que tener en cuenta que los bitmaps consumen mucha memoria, por eso hay que ser cautos cuando los utilicemos. Como referencia, una imagen de 100x100 consume cerca de 40 KB, una de 500x500 prácticamente 1 MB, y una de 1000x1000 3'8 MB.</p>
<h4>Resumiendo</h4>
<p>Como hemos visto, crear imágenes es una tarea muy sencilla. Sólo es importante entender cómo funciona el color (que lo vimos anteriormente) y saber que éste viene marcado por el booleano que indica si se soporta transparencia o no.</p>
<p>También es bueno comprender las ventajas que aporta tener las clases separadas y la limitación del tamaño de un bitmap.</p>
<blockquote><p>Al final, este capítulo también ha sido más teórico de lo que en un principio tenía en mente. Y aunque prefiero asentar conceptos que considero importantes antes que correr mucho, no olvido que dije que me centraría en la manipulación de pixels. Así pues, el próximo artículo lo dedicaré enteramente a jugar con los pixels, y mostraré algunas técnicas para crear efectos bastante interesantes. Prometido ;)</p></blockquote>
<hr />
<p><small>
<a href="http://llops.com/blog/2008/01/27/jugando-con-pixels-ii/#comments">6 comentarios</a>
<br/>
<a href="http://twitter.com/share?url=http://llops.com/blog/2008/01/27/jugando-con-pixels-ii/&text=Leyendo%20%22Jugando con pixels (II)%22&via=llops%20blog">Compartir en Twitter</a> | 
<a href="http://www.facebook.com/sharer.php?u=http://llops.com/blog/2008/01/27/jugando-con-pixels-ii/&t=Jugando con pixels (II)">Compartir en Facebook</a>

<br/><br/>
© <a href="http://llops.com/blog">llops blog</a> 2008 
</small></p>]]></content:encoded>
			<wfw:commentRss>http://llops.com/blog/2008/01/27/jugando-con-pixels-ii/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Jugando con pixels (I)</title>
		<link>http://llops.com/blog/2008/01/20/jugando-con-pixels-i/</link>
		<comments>http://llops.com/blog/2008/01/20/jugando-con-pixels-i/#comments</comments>
		<pubDate>Sun, 20 Jan 2008 18:00:47 +0000</pubDate>
		<dc:creator>llops</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[bitmap]]></category>
		<category><![CDATA[bitmapData]]></category>
		<category><![CDATA[color]]></category>
		<category><![CDATA[pixel]]></category>
		<category><![CDATA[vector]]></category>

		<guid isPermaLink="false">http://llops.com/blog/2008/01/20/jugando-con-pixels-i/</guid>
		<description><![CDATA[Empieza aquí una nueva serie de artículos, esta vez dedicados a la programación bitmap, y más concretamente, enfocados en la manipulación de imágenes a nivel de píxel. En la categoría Lab encontrarás una muestra de las cosas que se pueden hacer jugando con pixels. La programación bitmap es uno de los temas más extensos y [...]]]></description>
			<content:encoded><![CDATA[<p>Empieza aquí una nueva serie de artículos, esta vez dedicados a la programación bitmap, y más concretamente, enfocados en la manipulación de imágenes a nivel de píxel. En la categoría Lab encontrarás una <a title="Tag pixel" href="http://llops.com/blog/tag/pixel/" target="_blank">muestra</a> de las cosas que se pueden hacer jugando con pixels.</p>
<p>La programación bitmap es uno de los temas más extensos y complejos que se pueden encontrar en AS3. Por otro lado, también es uno de los temas más apasionantes de este lenguaje, y merece la pena invertir horas en su aprendizaje.</p>
<p>El mayor problema que me encontré cuando decidí aprender sobre esta temática es la poca información que existe al respecto (poca en inglés, y prácticamente nula en español), así que al final, la mayoría de cosas que aprendí fue en base a experimentación y a invertir días enteros intentando descifrar códigos que encontraba por la red. Espero con estos artículos cubrir un poco el vacío existente en este campo. Vamos allá.</p>
<blockquote><p><strong>Nota</strong>: antes de sumergirnos en el código, es muy importante comprender cómo se componen las imágenes y los pixels, por eso he preferido dedicar este primer capítulo a la teoría de estos temas.</p></blockquote>
<p><span id="more-18"></span></p>
<h4>Introducción</h4>
<p>La clase <em>BitmapData</em> permite trabajar con la información de una imagen. Fue introducida por Macromedia en Flash 8, y junto ella un nuevo abanico de posibilidades para manipular imágenes, añadir filtros, etc. Fue probablemente uno de los añadidos más importantes del lenguaje hasta la fecha.</p>
<p>Cabe recordar que Flash siempre ha sido una herramienta que trabaja con vectores, y hasta la llegada de Flash 8 apenas se podía hacer nada con las imágenes. Todo se reducía a poder cargarlas dinámicamente.</p>
<p>Veamos un poco esto dos formatos.</p>
<h4>Vectores vs mapa de bits</h4>
<p>Un vector es un gráfico que se construye en base a una descripción matemática. Los vectores trabajan con primitivas básicas como puntos, líneas y círculos. Por ejemplo, para dibujar una línea se necesita un punto inicial (x0,y0) y un punto final (x1,y1). La información que haya entre estos los puntos es generada en base a una ecuación.</p>
<p>Debido a esta forma de trabajar, un vector se puede escalar tanto como se desee sin perder calidad (se ve igual de nítido siempre), ya que lo único que se hace es alejar o acercar los puntos que conforman la figura. Esto permite tener archivos tan grandes como se quiera sin que aumente el peso del mismo, ya que siempre baraja la misma información.</p>
<p>Por el contrario, una imagen o mapa de bits (bitmap en inglés), es una cuadrícula de valores de color. Cada celda representa un pixel, que es la menor unidad en la que se descompone una imagen. Una imagen de 20x20 pixels tiene 400 valores de información, describiendo cada uno un color. En cuanto se intenta escalar un bitmap, el pixel se convierte en un rectángulo mayor y la imagen se distorsiona (se ve pixelada). El peso de una imagen depende entonces del tamaño de la misma, ya que a mayor tamaño mayor número de pixels y mayor número de información para guardar.</p>
<p>Pero no todo son desventajas para los bitmaps. Para imágenes complejas, se necesitarían tantos vectores para describir la figuras y colores que el tamaño resultante del archivo sería mucho mayor. Además, al tener que calcular las ecuaciones para dibujar el vector, todo el trabajo recae en el procesador del ordenador, con lo que la CPU se puede resentir de manera notable. Esto ha sido muy corriente en Flash, cuando veíamos animaciones espectaculares que se ralentizaban en ordenadores menos potentes.</p>
<p>Para más información sobre estos formatos, como siempre, a la <a title="Wikipedia - Gráfico Vectorial" href="http://es.wikipedia.org/wiki/Gr%C3%A1fico_vectorial" target="_blank">wiki</a>.</p>
<h4>Valores de color</h4>
<p>Como ya hemos dicho, un pixel es un minúsculo cuadrado de color. Es <strong>muy importante entender bien cómo se compone el color</strong> para poder trabajar con las imágenes, así que intentemos asimilar bien los siguientes conceptos.</p>
<blockquote><p><strong>Nota</strong>: aunque intentaré explicarlo lo más detallado posible, asumo que el lector tiene un conocimiento básico del sistema binario y hexadecimal.</p></blockquote>
<p>En ActionScript el color se representa como un entero de 32 bits (4 bytes), y esto nos proporciona un rango de 4.294.967.296 (2^32) valores. Cada uno de estos 4 bytes representa un canal de color: 3 de ellos son los colores primarios: rojo, verde y azul, lo que se conoce en inglés como RGB (red, green, blue), y el cuarto representa la transparencia o color Alfa. La intensidad de cada color viene determinada por un valor comprendido entre 0 y 255. La intensidad total es 255 mientras que 0 representa la ausencia de color.</p>
<blockquote><p>Este rango no es aleatorio. De 0 a 255 significa que existen 256 valores, que es el número que obtenemos si elevamos 2^8.<br />
8 son los bits que hay en cada canal, o lo que es lo mismo, el byte de cada canal. Cada color en ActionScript tienes 32 bits o 4 bytes.</p></blockquote>
<p>La intensidad en los colores RGB combinada forma las diferentes gamas de colores, mientras que la intensidad en el canal Alpha proporciona la transparencia. Así pues, con los 3 bytes (24 bits) de RGB tenemos un rango de 16.777.216 de valores (2^24), y a cada uno de estos valores le podemos dar 256 niveles de transparencia.</p>
<p>Al formar un color, se empieza por el canal alfa, seguido del rojo, verde y azul:</p>
<ul>
<li>Alfa: bits del 24 al 31</li>
<li>Rojo: bits del 16 al 23</li>
<li>Verde: bits del 8 al 15</li>
<li>Azul: bits del 0 al 7</li>
</ul>
<p>Por ejemplo, una representación del color azul puro sería:<br />
Alfa = 255, Rojo = 0, Verde = 0, Azul = 255</p>
<p>En binario quedaría como sigue:<br />
11111111 - 00000000 - 00000000 - 11111111    -&gt; 32 bits</p>
<p>Y en decimal tendríamos el valor:<br />
4.278.190.335</p>
<p>Es evidente que un número así no es muy fácil de recordar, por eso cuando hablamos de colores web se trabaja en formato hexadecimal. Un número hexadecimal comprende los 10 números de nuestro formato decimal más 6, de ahí que se conozca como base16:<br />
0-1-2-3-4-5-6-7-8-9-A(10)-B(11)-C(12)-D(13)-E(14)-F(15)</p>
<p>Para indicar que es hexadecimal, se utiliza el prefijo 0x.<br />
Algunos ejemplos de números hexadecimales (se multiplica por 16 por ser su base):</p>
<p>0x00 representa 0     -&gt;  0*16 + 0*1 = 0 + 0 = 0</p>
<p>0x15 representa  21   -&gt;  1*16 + 5*1 = 16 + 5 = 21</p>
<p>0x6A representa 106  -&gt;  6*16 + 10*1 = 96 + 10 = 106</p>
<p>0xFF representa 255   -&gt;  15*16 + 15*1 = 240 + 15 = 255</p>
<p>Entendiendo cómo funciona, es fácil deducir que un número hexadecimal de 32 bits se representa como 4 pares de valores hexadecimales:</p>
<p>0x          FF          FF          FF          FF<br />
prefijo    alfa        rojo       verde     azul</p>
<p>Finalmente, ya podemos ver que nuestro color azul se representaría como:<br />
0xFF0000FF</p>
<p>Esta nomenclatura es mucho más intuitiva y nos ayuda a leer e interpretar fácilmente una gran variedad de colores.</p>
<p>Para acabar de asimilar perfectamente estos conceptos, he credo un pequeño selector de color en el que se pueden modificar por separado los valores de cada canal y leer los resultados en formato decimal y hexadecimal.</p>
<p>
<object width="450" height="250">
<param name="movie" value="/blog/content/articulos/ene08/selector_color.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="450" height="250" src="/blog/content/articulos/ene08/selector_color.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/ene08/selector_color.zip" target="_blank">Descargar ejemplo</a></p>
<p>Vamos a fijarnos en algunas cosas:</p>
<ul>
<li>Cuando los colores primarios (RGB) tienen el valor 0, el color es negro puro</li>
<li>Cuando los colores primarios (RGB) tienen el valor 255, es blanco puro</li>
<li>Un color sólo es opaco cuando el canal alfa tiene el valor 255. Cualquier otro valor nos proporciona un color transparente.</li>
<li>Si los 4 canales están a 255, vemos que el número decimal es 4.294.967.295, y si le sumamos el 0 inicial tenemos el rango de colores de ActionScript que comentábamos al principio: 4.294.967.296</li>
<li>El modelo RGB se basa en la <a title="Wikipedia - Síntesis aditiva" href="http://es.wikipedia.org/wiki/S%C3%ADntesis_aditiva_de_color" target="_blank">síntesis aditiva</a>, por eso la suma de los colores puros dan estos otros colores:<br />
- Rojo y Verde = Amarillo (0x FF FF FF 00)<br />
- Rojo y Azul = Púrpura (0x FF FF 00 FF)<br />
- Verde y Azul = Cyan (0x FF 00 FF FF)</li>
</ul>
<p>Por último, indicar que en AS3 los colores se representa con el tipo de dato <em>uint</em>, que es un entero de 32 bits sin signo (siempre es positivo). Al no admitir valores negativos, el valor máximo es el doble que el de un tipo <em>int</em>, que admite 32 bits con signo.</p>
<blockquote><p>Rango uint: de 0 a 4,294,967,295 (2^32-1)<br />
Rango int: de -2,147,483,648 (-2^31) hasta 2,147,483,647 (2^31-1).</p></blockquote>
<p>Un color se declararía así:</p>
<div class="igBar"><span id="lactionscript3-71"><a href="#" onclick="javascript:showCodeTxt('actionscript3-71'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-71">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> color_rojo:<span style="color: #000099;">uint</span> = 0xFFFF0000; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<h4>Colores sin transparencia</h4>
<p>Hay que advertir que en la mayoría de los casos, cuando manipulamos objetos en ActionScript, el canal alfa no se modifica mediante el color, sino mediante la propiedad <em>alpha</em> (que define <em>DisplayObject</em>). Por ejemplo, cuando utilizamos el método <em>beginFill</em> de la propiedad <em>graphics</em>, vemos que la firma es</p>
<blockquote><p>beginFill (color:uint, alpha:Number = 1.0):void</p></blockquote>
<p>Aunque el tipo del color sea <em>uint</em>, se ignora la transparencia, ya que se aplica mediante su propiedad <em>alpha</em>. Si queremos que el color sea rojo, es lo mismo usar 0xFFFF0000 que 0xFF0000. Si tiene 4 pares hexadecimales, el primer par no se tiene en cuenta.</p>
<p>Veamos un ejemplo donde pasamos un canal alpha semitransparente, con valor 0x55. Al probar este código, vemos que el rojo es completamente opaco, ya que el canal alfa se ha ignorado:</p>
<div class="igBar"><span id="lactionscript3-72"><a href="#" onclick="javascript:showCodeTxt('actionscript3-72'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-72">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> s:<span style="color: #000099;">Shape</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">Shape</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">s.<span style="color: #000099;">graphics</span>.<span style="color: #555;">beginFill</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#40;</span>0x55FF0000,<span style="color: #FF0000;color:#000099;">1</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">s.<span style="color: #000099;">graphics</span>.<span style="color: #555;">drawCircle</span><span style="color: #555;">&#40;</span><span style="color: #FF0000;color:#000099;">0</span>,<span style="color: #FF0000;color:#000099;">0</span>,<span style="color: #FF0000;color:#000099;">10</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">s.<span style="color: #000099;">graphics</span>.<span style="color: #555;">endFill</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">addChild<span style="color: #555;">&#40;</span>s<span style="color: #555;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Esta es la razón por la que al definir colores en CSS, en Graphics, etc. se utilizan colores de 3 pares hexadecimales (0xFF0000). Como norma general, sólo se utiliza el canal alpha cuando trabajamos con bitmaps que admiten transparencia.</p>
<h4>Resumiendo</h4>
<p>Aunque la teoría siempre es pesada, un buen entendimiento de estos conceptos es clave para manipular las imágenes. El siguiente capítulo será más divertido, ya que nos meteremos de lleno en las clases Bitmap y BitmapData.</p>
<hr />
<p><small>
<a href="http://llops.com/blog/2008/01/20/jugando-con-pixels-i/#comments">14 comentarios</a>
<br/>
<a href="http://twitter.com/share?url=http://llops.com/blog/2008/01/20/jugando-con-pixels-i/&text=Leyendo%20%22Jugando con pixels (I)%22&via=llops%20blog">Compartir en Twitter</a> | 
<a href="http://www.facebook.com/sharer.php?u=http://llops.com/blog/2008/01/20/jugando-con-pixels-i/&t=Jugando con pixels (I)">Compartir en Facebook</a>

<br/><br/>
© <a href="http://llops.com/blog">llops blog</a> 2008 
</small></p>]]></content:encoded>
			<wfw:commentRss>http://llops.com/blog/2008/01/20/jugando-con-pixels-i/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Programando en AS3 desde Flash CS3 (III)</title>
		<link>http://llops.com/blog/2007/12/21/programando-en-as3-desde-flash-cs3-iii/</link>
		<comments>http://llops.com/blog/2007/12/21/programando-en-as3-desde-flash-cs3-iii/#comments</comments>
		<pubDate>Fri, 21 Dec 2007 20:01:14 +0000</pubDate>
		<dc:creator>llops</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[attachMovie]]></category>
		<category><![CDATA[base Class]]></category>
		<category><![CDATA[Error #1136]]></category>
		<category><![CDATA[flash cs3]]></category>
		<category><![CDATA[linkage]]></category>

		<guid isPermaLink="false">http://llops.com/blog/2007/12/21/programando-en-as3-desde-flash-cs3-iii/</guid>
		<description><![CDATA[Vamos con el tercer y último artículo de la serie, dedicado a la forma en que se utilizan los objetos que tenemos en la librería de Flash. Este artículo es menos técnico que los anteriores, pero dado que el cambio es bastante significativo (ya no se utiliza más attachMovie) merece la pena tratarlo. Desde flash [...]]]></description>
			<content:encoded><![CDATA[<p>Vamos con el tercer y último artículo de la serie, dedicado a la forma en que se utilizan los objetos que tenemos en la librería de Flash.</p>
<p>Este artículo es menos técnico que los anteriores, pero dado que el cambio es bastante significativo (ya no se utiliza más <em>attachMovie</em>) merece la pena tratarlo.</p>
<p><span id="more-16"></span></p>
<p>Desde flash 5, cuando queríamos utilizar un símbolo de la librería de manera dinámica, le dábamos un nombre de identificador y con "attachMovie" lo vinculábamos a nuestra película. En flash 8, además, teníamos un campo para asociar el clip a una clase de ActionScript 2.</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/dic07/vinculacion_flash8.jpg" alt="" width="397" height="179" /></p>
<p class="img-comment">Panel de vinculación de Flash 8</p>
<p>Para cualquier programador actionscript, la sintaxis de attachMovie le resultará tan familiar como engorrosa. Gracias a Dios, en Flash CS3 esto ha pasado a mejor vida.</p>
<h4>Utilizando clips de la biblioteca en CS3</h4>
<p>Como ya hemos comentado en los artículos anteriores, en AS3 todo se traduce a clases, así que si queremos utilizar un clip que tenemos en nuestra librería tenemos que crear una nueva clase. Vamos a verlo paso a paso.</p>
<p>Dibujamos una bola en el escenario de Flash y la transformamos a MovieClip (F8). En la biblioteca, seleccionamos nuestro MovieClip y buscamos la opción de Linkage.</p>
<p><img class="centered" src="http://llops.com/blog/content/articulos/dic07/library_cs3.jpg" alt="" /></p>
<p class="img-comment">Librería y panel de vinculación de Flash CS3</p>
<p>Marcamos el checkbox <em>Export for ActionScript</em> y se activan dos campos de texto. En el primero ponemos <em>BolaClass</em>, que será el nombre de nuestra clase. El segundo, como el nombre indica, es la clase de la cual hereda (podemos usar la clase base que queramos, lo veremos luego). De momento dejamos MovieClip. Al darle <em>OK</em> veremos que aparece el siguiente mensaje:</p>
<blockquote><p>A definition for this class could not be found in the classpath, so one will be automatically generated in the SWF file upon export.</p></blockquote>
<p>Flash nos advierte que no encuentra <em>BolaClass</em> en su ruta de clases, así que generará una clase automáticamente al exportar. Al igual que pasa con el <em>document Class</em>, cuando Flash CS3 necesita una clase y no la encuentra la genera él mismo. El mismo mensaje aparece si le damos al check verde o al lápiz.</p>
<p>Ahora que ya tenemos el clip exportado para ActionScript podemos crear bolas dinámicamente. El código es más fácil, limpio e intuitivo que <em>attachMovie</em>.</p>
<div class="igBar"><span id="lactionscript3-76"><a href="#" onclick="javascript:showCodeTxt('actionscript3-76'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-76">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> bola = <span style="color: #1518ff;">new</span> BolaClass<span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>; <span style="color: #F0F; font-style: italic;">// crea un nuevo objeto bolaClass</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">addChild<span style="color: #555;">&#40;</span>bola<span style="color: #555;">&#41;</span>;&nbsp; &nbsp;<span style="color: #F0F; font-style: italic;">// añade el objeto al escenario </span></div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<h4>Dándole un comportamiento a nuestra clase</h4>
<p>Si queremos dotar de comportamiento a nuestro clip, podemos escribir la clase nosotros en vez de dejar que lo haga automáticamente el compilador. De esta manera, tendremos el aspecto lógico y gráfico ligados.</p>
<p>Por ejemplo, vamos a hacer que nuestra bola, cada x segundos, desaparezca de su posición y aparezca en una nueva. Para ello creamos una nueva clase llamada BolaClass en la misma carpeta que tenemos el fla. El código podría ser algo así:</p>
<div class="igBar"><span id="lactionscript3-77"><a href="#" onclick="javascript:showCodeTxt('actionscript3-77'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-77">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">package</span> <span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">import</span> flash.<span style="color: #555;">display</span>.<span style="color: #000099;">MovieClip</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">import</span> fl.<span style="color: #555;">transitions</span>.<span style="color: #555;">Tween</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">import</span> fl.<span style="color: #555;">transitions</span>.<span style="color: #555;">TweenEvent</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">import</span> fl.<span style="color: #555;">transitions</span>.<span style="color: #555;">easing</span>.<span style="color: #555;">Strong</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">import</span> flash.<span style="color: #555;">utils</span>.<span style="color: #000099;">Timer</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">import</span> flash.<span style="color: #555;">events</span>.<span style="color: #000099;">TimerEvent</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">public</span> <span style="color: #1518ff;">class</span> BolaClass <span style="color: #1518ff;">extends</span> <span style="color: #000099;">MovieClip</span><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">var</span> _ancho:<span style="color: #000099;">int</span> = <span style="color: #FF0000;color:#000099;">300</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">var</span> _alto:<span style="color: #000099;">int</span> = <span style="color: #FF0000;color:#000099;">150</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">var</span> _tweenAlpha:Tween;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">var</span> _tweenX:Tween;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">var</span> _tweenY:Tween;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">function</span> BolaClass<span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">alpha = <span style="color: #FF0000;color:#000099;">0</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #F0F; font-style: italic;">// Crear un delay aleatorio para comenzar</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> retardo:<span style="color: #000099;">Number</span> = <span style="color: #000099;">Math</span>.<span style="color: #555;">random</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span> * <span style="color: #FF0000;color:#000099;">2000</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> t:<span style="color: #000099;">Timer</span> = <span style="color: #1518ff;">new</span> <span style="color: #000099;">Timer</span><span style="color: #555;">&#40;</span>retardo, <span style="color: #FF0000;color:#000099;">1</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">t.<span style="color: #555;">addEventListener</span><span style="color: #555;">&#40;</span><span style="color: #000099;">TimerEvent</span>.<span style="color: #555;">TIMER_COMPLETE</span>, comenzar<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">t.<span style="color: #555;">start</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">function</span> comenzar<span style="color: #555;">&#40;</span>e:<span style="color: #000099;">TimerEvent</span><span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">aparecer<span style="color: #555;">&#40;</span><span style="color: #000099;">null</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">function</span> aparecer<span style="color: #555;">&#40;</span>e:TweenEvent<span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">x = <span style="color: #000099;">Math</span>.<span style="color: #555;">random</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span> * _ancho;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">y = <span style="color: #000099;">Math</span>.<span style="color: #555;">random</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span> * _alto;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> tiempo:<span style="color: #000099;">Number</span> = <span style="color: #FF0000;color:#000099;">1</span> + <span style="color: #000099;">Math</span>.<span style="color: #555;">random</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span> * <span style="color: #FF0000;color:#000099;">3</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_tweenAlpha = <span style="color: #1518ff;">new</span> Tween<span style="color: #555;">&#40;</span><span style="color: #000099;">this</span>, <span style="color: #555;">"alpha"</span>, Strong.<span style="color: #555;">easeOut</span>, <span style="color: #FF0000;color:#000099;">0</span>, <span style="color: #FF0000;color:#000099;">1</span>, tiempo, <span style="color: #000099;">true</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_tweenX = <span style="color: #1518ff;">new</span> Tween<span style="color: #555;">&#40;</span><span style="color: #000099;">this</span>, <span style="color: #555;">"scaleX"</span>, Strong.<span style="color: #555;">easeOut</span>, <span style="color: #FF0000;color:#000099;">0</span>, <span style="color: #FF0000;color:#000099;">1</span>, tiempo, <span style="color: #000099;">true</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_tweenY = <span style="color: #1518ff;">new</span> Tween<span style="color: #555;">&#40;</span><span style="color: #000099;">this</span>, <span style="color: #555;">"scaleY"</span>, Strong.<span style="color: #555;">easeOut</span>, <span style="color: #FF0000;color:#000099;">0</span>, <span style="color: #FF0000;color:#000099;">1</span>, tiempo, <span style="color: #000099;">true</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_tweenAlpha.<span style="color: #555;">addEventListener</span><span style="color: #555;">&#40;</span>TweenEvent.<span style="color: #555;">MOTION_FINISH</span>, desaparecer<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">private</span> <span style="color: #1518ff;">function</span> desaparecer<span style="color: #555;">&#40;</span>e:TweenEvent<span style="color: #555;">&#41;</span>:<span style="color: #000099;">void</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> tiempo:<span style="color: #000099;">Number</span> = <span style="color: #FF0000;color:#000099;">1</span> + <span style="color: #000099;">Math</span>.<span style="color: #555;">random</span><span style="color: #555;">&#40;</span><span style="color: #555;">&#41;</span> * <span style="color: #FF0000;color:#000099;">2</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_tweenAlpha = <span style="color: #1518ff;">new</span> Tween<span style="color: #555;">&#40;</span><span style="color: #000099;">this</span>, <span style="color: #555;">"alpha"</span>, Strong.<span style="color: #555;">easeIn</span>, <span style="color: #FF0000;color:#000099;">1</span>, <span style="color: #FF0000;color:#000099;">0</span>, tiempo, <span style="color: #000099;">true</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_tweenX = <span style="color: #1518ff;">new</span> Tween<span style="color: #555;">&#40;</span><span style="color: #000099;">this</span>, <span style="color: #555;">"scaleX"</span>, Strong.<span style="color: #555;">easeIn</span>, <span style="color: #FF0000;color:#000099;">1</span>, <span style="color: #FF0000;color:#000099;">0</span>, tiempo, <span style="color: #000099;">true</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_tweenY = <span style="color: #1518ff;">new</span> Tween<span style="color: #555;">&#40;</span><span style="color: #000099;">this</span>, <span style="color: #555;">"scaleY"</span>, Strong.<span style="color: #555;">easeIn</span>, <span style="color: #FF0000;color:#000099;">1</span>, <span style="color: #FF0000;color:#000099;">0</span>, tiempo, <span style="color: #000099;">true</span><span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">_tweenAlpha.<span style="color: #555;">addEventListener</span><span style="color: #555;">&#40;</span>TweenEvent.<span style="color: #555;">MOTION_FINISH</span>, aparecer<span style="color: #555;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #555;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Una vez lista la clase, probemos a crear varias bolas en el escenario, por programación o arrastrándolas directamente desde la biblioteca. Ya tenemos nuestro clip con su comportamiento específico:</p>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/dic07/simbolo_biblioteca.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/dic07/simbolo_biblioteca.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p style="text-align: center;"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/dic07/simbolo_biblioteca.zip" target="_blank">Descargar ejemplo</a></p>
<p>Cabe resaltar, que ahora que tenemos nuestra clase, si abrimos el panel de vinculación y le damos al check verde veremos este mensaje:</p>
<blockquote><p>The definition for this class was found at <em>[ruta de la clase]</em></p></blockquote>
<p>en vez del mensaje anterior donde nos decía que generaría la clase él mismo. Y si clicamos en el lápiz Flash nos abrirá el .as en el IDE.</p>
<h4>Utilizando nuestra propia clase base</h4>
<p>Como hemos dicho antes, al margen de los símbolos por defecto, podemos utilizar cualquier tipo de clase como base (siempre que tenga coherencia). Por ejemplo, en nuestro ejemplo de la bola, la clase base podría haber sido perfectamente Sprite.</p>
<p>Pero la herencia no se limita sólo a las clases nativas de Flash, sino que pueden ser propias. Esto es útil cuando queremos dotar de comportamiento a múltiples objetos.</p>
<p>Sobre el ejemplo de la bola, imaginemos que queremos que otros objetos como un cuadrado y un triángulo tengan su comportamiento (cambiar de posición mediante un fundido). Una opción sería generar una clase para cada objeto. ¿Pero qué pasa si tengo 20 tipos de objetos diferentes? ¿Y si en vez de ser una clase sencilla son cientos de líneas? En este caso es más útil aislar el comportamiento y que lo utilicen todos los objetos. Vamos a verlo:</p>
<ol>
<li>Creamos una clase: Fundido.as<br />
El código es el mismo que el utilizado en BolaClass, así que sólo tenemos que cambiar el nombre de la clase y el nombre del constructor.</li>
<li>Igual que hicimos con la bola, creamos dos MovieClips más, un cuadrado y un triángulo.</li>
<li>En el panel de vinculación, le damos los siguientes nombres respectivamente: <em>BolaClass</em>, <em>CuadradoClass</em> y <em>TrianguloClass</em> (las clases no deben existir, dejamos que las cree el compilador)</li>
<li>En el campo de la clase base, ponemos <em>Fundido</em>.<br />
<img class="centered" src="http://llops.com/blog/content/articulos/dic07/vinculacion_triangulo.jpg" alt="" /></li>
<li>Añadimos al escenario los clips y probamos la película.</li>
</ol>
<p>
<object width="300" height="150">
<param name="movie" value="/blog/content/articulos/dic07/multiples_simbolos.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="300" height="150" src="/blog/content/articulos/dic07/multiples_simbolos.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p class="swf-comment"><a title="Descargar ejemplo" href="http://llops.com/blog/content/articulos/dic07/multiples_simbolos.zip" target="_blank">Descargar ejemplo</a></p>
<h4>Tipo de símbolos para exportar</h4>
<p>Para acabar, vamos a ver los tipos de símbolos que utiliza Flash CS3. Decíamos que el parámetro <em>Base class</em> viene dado por el tipo de símbolo que utilizamos. Cuando convertimos a símbolo, Flash nos da estas opciones:</p>
<ul>
<li>MovieClip - utiliza la clase base flash.display.MovieClip</li>
<li>Button - utiliza la clase base flash.display.SimpleButton</li>
<li>Graphic - no se puede utilizar de manera dinámica, por lo tanto no está disponible para exportar.</li>
</ul>
<p>Además, a través de la opción de importar, podemos generar dos tipos más de contenido para utilizar de manera dinámica:</p>
<ul>
<li>Imágenes - hereda de flash.display.BitmapData</li>
<li>Audio - hereda de flash.media.Sound</li>
</ul>
<p><img class="centered" src="http://llops.com/blog/content/articulos/dic07/simbolos_libreria.jpg" alt="" /></p>
<p class="img-comment">Tipo de símbolos que se pueden usar en la librería de manera dinámica</p>
<p>El funcionamiento es exactamente igual para todos: definimos un nombre de clase y mediante <em>new</em> la instanciamos. La única clase base que tiene una peculiaridad es <em>BitmapData</em>. Si le damos a nuestra imagen el nombre <em>ImagenClass</em> y probamos a crear una mediante <em>new</em> veremos este error:</p>
<blockquote><p>1136: Incorrect number of arguments.  Expected 2.</p></blockquote>
<p>Esto es debido a que el constructor de esta clase espera dos parámetros: anchura y altura. Aunque en teoría debería ser la anchura y altura de la imagen, conque le pasemos un número (negativo, decimal, con 20 cifras...) es suficiente. El compilador sobreescribe con los valores correctos (sí, no tiene mucho sentido).<br />
El código sería similar a este:</p>
<div class="igBar"><span id="lactionscript3-78"><a href="#" onclick="javascript:showCodeTxt('actionscript3-78'); return false;">Plain Text</a></span></div>
<div class="syntax_hilite">
<div id="actionscript3-78">
<div class="actionscript3">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> img = <span style="color: #1518ff;">new</span> ImgClass<span style="color: #555;">&#40;</span><span style="color: #FF0000;color:#000099;">0</span>,<span style="color: #FF0000;color:#000099;">0</span><span style="color: #555;">&#41;</span>; <span style="color: #F0F; font-style: italic;">// Instanciamos una imagen de nuestra librería</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #1518ff;">var</span> bmp = <span style="color: #1518ff;">new</span> <span style="color: #000099;">Bitmap</span><span style="color: #555;">&#40;</span>img<span style="color: #555;">&#41;</span>;&nbsp; &nbsp;<span style="color: #F0F; font-style: italic;">// Creamos un objeto Bitmap para contenerla</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#666666;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">addChild<span style="color: #555;">&#40;</span>bmp<span style="color: #555;">&#41;</span>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #F0F; font-style: italic;">// Lo añadimos a la lista de visualización </span></div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<h4>Resumiendo</h4>
<p>Con la llegada de AS3 todo gana en coherencia, y no sólo en cuanto a código se refiere. También ha obligado a Flash CS3 a cumplir en este sentido, y ahora utilizar nuestros clips de biblioteca de manera dinámica es tan fácil como darle un nombre de clase (que además no estamos obligados a crear) e instanciarla mediante el operador <em>new</em>.</p>
<p>Además, con la posibilidad de utilizar una clase base para nuestros objetos, gana fuerza la opción de herencia frente composición, aunque en muchos casos seguirá siendo preferible ésta última.</p>
<hr />
<p><small>
<a href="http://llops.com/blog/2007/12/21/programando-en-as3-desde-flash-cs3-iii/#comments">6 comentarios</a>
<br/>
<a href="http://twitter.com/share?url=http://llops.com/blog/2007/12/21/programando-en-as3-desde-flash-cs3-iii/&text=Leyendo%20%22Programando en AS3 desde Flash CS3 (III)%22&via=llops%20blog">Compartir en Twitter</a> | 
<a href="http://www.facebook.com/sharer.php?u=http://llops.com/blog/2007/12/21/programando-en-as3-desde-flash-cs3-iii/&t=Programando en AS3 desde Flash CS3 (III)">Compartir en Facebook</a>

<br/><br/>
© <a href="http://llops.com/blog">llops blog</a> 2007 
</small></p>]]></content:encoded>
			<wfw:commentRss>http://llops.com/blog/2007/12/21/programando-en-as3-desde-flash-cs3-iii/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

