Programando en AS3 desde Flash CS3 (I)
AS3 no es difÃcil, y si se tiene una buena base de AS2 (o de otros lenguajes como C# o Java) el cambio no es muy doloroso. Una persona con conocimientos de programación orientada a objetos que empiece en Flex Builder un "Proyecto ActionScript" (sólo código) no tendrá muchas dificultades (evidentemente tendrá que conocer la sintaxis). En cambio, esta misma persona comenzando con Flash, tendrá que familiarizarse con conceptos como timeline o movieclip y entender la relación con el lenguaje.
El problema es que, en esta nueva versión, el programa se ha tenido que adaptar a las caracterÃsticas OOP del lenguaje, asà que también ha habido cambios que los programadores flash de toda la vida tenemos que asimilar (es muy difÃcil deshacerse de las viejas prácticas, y más si llevas 4 o 5 versiones del programa).
En este primer artÃculo vamos a ver qué significan las acciones que realizamos en el IDE de Flash desde el punto de vista de actionscript.
El Document class
Una de las novedades de CS3 es el Document class. Se trata de la clase principal asociada a una pelÃcula flash, o dicho de otra manera, el punto de arranque de la aplicación. Al declarar el Document class nos ahorramos tener que meter código en el fla.
Main es la clase asociada que se encuentra en el paquete com.llops
Veamos el código de nuestra clase Main:
-
package com.llops
-
{
-
import flash.display.MovieClip;
-
public class Main extends MovieClip
-
{
-
function Main(){
-
}
-
}
-
}
Vemos como la clase está declarada con el modificador public. Esto es un requisito al estar vinculada al document class.
Si especificamos un Document class que no existe, el compilador crea una clase con dicho nombre, y si no declaramos ninguno, el compilador asigna uno de manera transparente. Asà pues, todas las aplicaciones flash parten de una clase base.
La clase base debe extender de Sprite, pero si cuenta con código en algún frame o se quiere utilizar la lÃnea de tiempo lo ha de hacer de MovieClip (realmente hay algún caso más, pero de momento nos podemos quedar con los dos principales).
Cualquier código que añadamos en un frame del timeline principal pasará a ser parte de nuestra clase. Por ejemplo, añadamos el siguiente script en el frame1 del fla:
-
var texto:String = "diez";
-
function test():void{
-
var numero:int = 10;
-
trace(texto, numero);//Output: diez 10
-
}
-
test();
Al compilar el swf, la clase quedarÃa prácticamente de la siguiente manera:
-
package com.llops
-
{
-
import flash.display.MovieClip;
-
public class Main extends MovieClip
-
{
-
public var texto:String = "diez";
-
function Main() {
-
test();
-
}
-
public function test():void {
-
var numero:int = 10;
-
trace(texto, numero);//Output: diez 10
-
}
-
}
-
}
Al igual que pasa con la clase, por estar declaradas en la lÃnea de tiempo, tanto la variable como la función utilizarán el modificador public.
Llegados a este punto, hemos de quedarnos que una de las principales novedades es que, al compilar nuestra pelÃcula, todo lo que hayamos hecho en el IDE se traduce a clases en AS3. Esto es válido tanto para código como para los movieclips, gráficos y botones que añadamos en el escenario.
Añadiendo movieclips manualmente al escenario
Si utilizamos flash como herramienta es porque queremos hacer uso de sus capacidades gráficas. Lo que en lenguajes como C++ llevarÃa horas en flash pueden ser unos pocos minutos.
Volvamos al punto en que no tenemos código en el fla y tenemos nuestra clase Main asociada al document class.
Creemos un movieclip en la biblioteca que tenga forma de cruz (MC Cruz). Arrastremos dos instancias en el escenario: una la dejaremos sin nombre de instancia y a la otra la llamaremos cruz_mc. Ahora añadamos las siguientes lÃneas en el constructor:
-
trace(getChildAt(0),getChildAt(0).name);
-
trace(getChildAt(1),getChildAt(1).name);
Al ejecutar la pelÃcula, en el panel de output, veremos lo siguiente:
[object MovieClip] instance1
[object MovieClip] cruz_mc
En la pelÃcula principal, existen dos objetos de la clase MovieClip (posiciones 0 y 1), con los nombres instance1 (asignado por el compilador) y cruz_mc (asignado por nosotros).
Sabiendo sus nombres no habrÃa ningún problema en hacer lo siguiente
-
trace(getChildByName("instance1"));
-
trace(getChildByName("cruz_mc"));
devolviendo dos objetos del tipo MovieClip.
¿Pero qué pasa si probamos el siguiente código?:
-
trace(instance1);
-
trace(cruz_mc);
El compilador arroja el siguiente error
1120: Access of undefined property instance1
ya que no existe ninguna propiedad en la clase que responda a instance1. Aunque nos saltáramos los errores de compilación, en tiempo de ejecución, nos saldrÃa:
Error #1065: No se ha definido la variable instance1.
Si comentamos la lÃnea que genera error, veremos que no hay ningún problema con la segunda, y el trace de cruz_mc devuelve [object MovieClip].
Cualquier objeto que se añade manualmente al escenario se añade también a la DisplayList, por esa razón hemos podido acceder a las dos cruces mediante los métodos getChildAt y getChildByName, definidos en la clase DisplayObjectContainer y que nuestra clase hereda al extender MovieClip.
Sin embargo, al hacer trace de instance1 nos genera un error, ya que no existe realmente ninguna propiedad ni variable definida como tal, sólo es el name que utiliza internamente el compilador para manipularlo como objeto visual. Sin embargo, cruz_mc no devuelve error ya que sà existe como variable de la clase Main. Es más, si utilizamos el debugger de flash podemos encontrar un puntero en memoria reservado para cruz_mc, mientras que no hay rastro de instance1. ¿Por qué?
La razón por la que existe dicha variable es que al trabajar con AS3 en Flash CS3, el compilador provee dos mecanismos para acceder a movieclips que hayan sido creados en lÃnea de tiempo y tengan nombre de instancia:
- Asigna el mismo nombre a una variable de la clase
- Declara dicha variable
Traducido a código, quedarÃa asÃ:
-
package com.llops
-
{
-
import flash.display.MovieClip;
-
public class Main extends MovieClip
-
{
-
// Mecanismo 2:
-
// Declara una variable del mismo tipo (movieclip)
-
public var cruz_mc:MovieClip;
-
function Main()
-
{
-
// Mecanismo 1:
-
// Asigna el movieclip a la variable
-
// haciendo coincidir el nombre
-
cruz_mc = getChildByName("cruz_mc");
-
}
-
}
-
}
Aunque pueda parecer que el orden de los mecanismos serÃa más acertado al revés (mecanismo 1 crear variable y mecanismo 2 asignarla), lo he puesto asà porque el mecanismo 1 se cumple siempre, mientras que el segundo depende de una opción que tenemos activada por defecto: Automatically declare stage instances.
Esta opción se encuentra en Publish Settings > ActionScript Settings

Si desmarcamos esta casilla y probamos a compilar obtenemos el siguiente error:
Error #1056: No se puede crear la propiedad cruz_mc en com.llops.Main.
Para que no haya problemas, debemos declarar manualmente el movieclip como variable de clase, sin olvidarnos que ha de ser pública:
-
public var cruz_mc:MovieClip;
Una vez hecho, el compilador mirará la variable, y al coincidir el nombre de instancia del movieclip con la variable, la asignará (mecanismo 1).
Si tenemos la opción marcada y además probamos a declarar la variable, el compilador nos dirá
1151: A conflict exists with definition cruz_mc in namespace internal.
debido a que ya existe.
Esto no sólo pasa con los MovieClips, sino con cualquier objeto al que le podamos dar un nombre de instancia en el escenario, como campos de texto (declarar como TextField) o botones (declarar como SimpleButton)
A priori, parece una gran utilidad que Flash CS3 declare por nosotros las variables, y más si tenemos muchÃsimos objetos en el escenario, pero esta solución acaba generando un código más difÃcil de seguir, ya que leyendo el código no sabemos de dónde salen las variables. Además, si se utiliza un editor externo como FlashDevelop o Flex Builder, marca errores o no te da las opciones de autocompletado debido a que no están declaradas.
En la práctica, esta opción me ha dado muchos más problemas que ventajas, asà que recomiendo desactivar el check siempre. Al fin y al cabo, esta es una de las mejores prácticas de los lenguajes OOP, tener que declarar todo para suministrar la máxima información posible al compilador.
Resumiendo
AS2, aunque nos da una sintaxis más cercana a OOP, no deja de ser un envoltorio que acaba compilando a actionscript1. Con la llegada de AS3 tenemos realmente un lenguaje orientado a objetos, y el compilador de flash ha tenido que adaptarse. Por ello, cualquier cosa que hagamos en el IDE de Flash tiene su correspondiente transformación a AS3. Todo (código en frames, movieclips en el escenario, etc) acaba compilándose en clases.
El Document class nos proporciona una manera fácil de asociar nuestro fla con la clase principal. Sino declaramos uno, el programa lo hará de manera transparente.
Por otro lado, el compilador nos provee de mecanismos para asignar nuestros objetos en pantalla a variables de clase.
De esta manera, si una persona sin conocimientos OOP elige un proyecto AS3 en Flash, aunque sólo utilice clips de pelÃcula en el escenario, animaciones e instrucciones sencillas tipo stop(), gracias a las nuevas funcionalidades del compilador, tendrá un verdadero programa orientado a objetos, aunque ni siquiera lo sepa.
Post publicado el 01 de December de 2007 a las 20:00 por llops
Categorias: ArtÃculos
Etiquetas: as3, document class, Error #1056, Error #1065, flash cs3
¿Quieres seguir los comentarios de esta entrada? RSS 2.0

9 comentarios
#1 Pludo
Es decir, los que - como yo - programábamos orientado a objetos sin saberlo, a partir de ahora nos vamos a tener que enterar de todo para seguir con nuestro trabajo. Uffff, no quiero parecer perezoso, pero....lo de declarar cada clip y todo...dan ganas de quedarse en Flash 8....arrrggss.
Dec 5, 2007
#2 LLops
Dependiendo del perfil, es normal que no se quiera pasar a un lenguaje tan "serio" como es as3, pero es que tampoco es necesario que todo el mundo dé el salto. As2 y as1 tienen cuerda para rato, y para un porcentaje altÃsimo de webs cumplen sobradamente.
Asà que si te sientes más cómodo a la vieja usanza, no pasa nada porque sigas por ahà ;)
Dec 5, 2007
#3 Lucas
LLops estas aclaraciones son fantasticas, pero me quedó colgado el tema del checkbox "Automatically declare stage instances".
A ver si entendi? al destildar esta opcion, el compilador ya no instancia automaticamente los objetos que estan en el escenario?
O sea cada vez que haga un addChild tengo que darle un .name a cada objeto? aunque no los utilice a traves del nombre de instancia?
Gracias y saludos
Dec 27, 2007
#4 LLops
No exactamente.
El .name no hay que modificarlo (es más, es una mala práctica). Accede por el nombre de la variable, y si, como dices, no utilizas el nombre de instancia, puedes hacerlo por su posición numérica. Ejemplo: getChildAt(1)
Lo que comentaba sólo sirve para los objetos que hemos añadido manualmente al escenario y les hemos dado un nombre. Si cumple estos dos requisitos hay dos posibilidades:
- Check tildado: el compilador declara la variable con el mismo nombre que tu le has dado.
- Check no tildado: el compilador no hace nada, entonces tú en tu clase debes crear la variable con el nombre haciendo que coincida. Sino te dará un error, ya que existe un objeto en el escenario pero no en la clase. El compilador tiene que saber que existe este objeto.
Espero que haya quedado claro. Un saludo!
Dec 27, 2007
#5 psycho-vnz
Muy buen artÃculo me ha despejado algunas dudas, ahora voy por el segundo.
Espero que hayan muchos mas acerca AS3, te explicas muy bien :D
Saludos
Jan 11, 2008
#6 Juan
Has ganado un nuevo lector con éste POST. ;)
Me suscribo al RSS!!
Un saludo.
Feb 15, 2008
#7 Eisen
Creo que me pasare amenudo por aquÃ. Felicidades
Apr 2, 2008
#8 TIMNHE
Hola LLops, hace poco que yo tambien he dado el salto, y tal como todos dicen, es genial y horrible al mismo tiempo :p
A mi lo que mas me preocupa es todo lo relacionado con como trabajar a la vieja usanza, y por ejemplo una de las cosas que no acabo de comprender es el tema de la variable root.
Esto me tiene loco, pero caso aparte, en el ejemplo que indicas más arriba, pones el caso de que los MovieClips que defines en tu clase, ya están en el escenario.
¿Como tratarÃas a un mc, si por ejemplo está en el fotograma 5?
Saludos!
May 1, 2008
#9 LLops
Hola Timnhe,
por lo que he ido viendo no eres el único que planteas estas dudas. Estoy pensando en escribir un cuarto artÃculo enfocado en casos prácticos...
De todas formas, y en cuanto a tu pregunta especÃfica, no hay que hacer nada especial si tienes un mc definido en un fotograma que no sea el primero. Sólo asegúrate de declarar la variable que coincida con el nombre que le des en el escenario, y el Flash Player, cuando alcance dicho fotograma, asignará el mc a dicha variable y ya la podrás manipular.
May 4, 2008
3 trackbacks
¡Deja un comentario!