Migrando AS3. Duda sobre rutas y lista visualizacion
Hola Hola!!
Ayer porfin me instale la version 9 de flash para comenzar a migrar a AS3.
Despues de estar testeando cosillas y usando varios manuales de adobe, hay ciertos conceptos nuevos que no me quedan claros, sobretodo en la puesta en practica y dado que programaba en as2 pero no usaba una OOP muy extricta (usea, que aunque creaba clases seguia usando mucha programación en root, no en clips pero si en root, al estilo as1) hay algunas cosas que se me escapan.
Bueno, a lo que iba, dudas practicas:
RUTAS en los objetos de AS3
1. Rutas:Nueva lista de visualización ('desaparicion' de _root).
<em>Testando AS3 y mirando la nueva metodologia para añadir clips y utilizarlos se me ha escapado una cosilla que me ha dado dolor de cabeza.</em>
Redacto mis dudas con un ejemplo por pasos.
1º El ejemplo en AS2
Pongamos que tenemos un mc en la libreria con link "simbolo"
Creamos los 3 simbolos, metiendo el 3 dentro del primero
<code>var simb0:MovieClip = _root.attachMovie("simbolo", "clip1", 1);
var simb1:MovieClip = _root.attachMovie("simbolo", "clip2", 2);
var simb3:MovieClip = simb0.attachMovie("simbolo", "clip1b", 1);
simb1._x += 60;
simb3._x += 30;</code>
Para acceder a ellos podemos acceder desde root usando las variables simb0,simb1 o simb3
<code>trace("Desde variable :: simb3._x="+simb3._x); //traza correctamente</code>
O desde cualquier otro sitio (incluyendo clases externas) usando la ruta completa
<code>trace("Desde ruta :: simb3._x="+_root.clip1.clip1b._x);</code>
Si tenemos una clase externa con esta ruta completa dentro tb funcionará (aunque no se si es del todo correcto).
Por ejemplo, la clase externa tiene este codigo:
<code>class clase {
function clase(trazar:String) {
trace("Desde clase: simb3._x="+_root.clip1.clip1b._x);
}
}</code>
Y el flash este:
<code>var miClase:clase=new clase("hola dmstk");
//Traza correctamente
</code>
2. Ahora en AS3
Pongamos que tenemos un mc en la libreria con class "simbolo"
Creamos los 3 simbolos, metiendo el 3 dentro del primero
<code>var simb0:simbolo = new simbolo();
addChild(simb0);
simb0.name="simb0";
var simb1:simbolo = new simbolo();
simb1.x=60;
simb1.name="simb1";
addChild(simb1);
var simb3:simbolo = new simbolo();
simb3.x=30;
simb3.name="simb3";
simb0.addChild(simb3);</code>
Para acceder a ellos podemos acceder desde el stage usando los nombres de objetos simb0,simb1 o simb3
<code>trace("Desde variable :: simb3._x=" + simb3.x); </code>
Ahora viene uno de mis problemas.
Sabiendo q _root ya no es lo que era), ya no me sirven el sistema de rutas por puntos de as2, con root o sin root:
<code>
trace("Desde ruta :: simb3._x="+root.clip1.clip1b.x); //Trace error => 1120: Access of undefined property root.
trace("Desde ruta :: simb3._x="+clip1.clip1b.x); //Trace error => 1120: Access of undefined property clip1.</code>
Pero si coloco los clips manualmente en el escenario si que rula este sistema
Ej: <em>metiendo un mc llamado "objetoPosicionado" dentro del cual hay uno llamado "objetoPosicionado2"</em>
<code>trace("Ruta insertados manualmente :: =" + objetoPosicionado.objetoPosicionado2.name); //trace => objetoPosicionado2
</code>
Porque funciona el sistema de rutas relativas por puntos si coloco los clips en el escenario en modo diseño pero no si los coloco mediante AS3???
Según me he fijado, si quiero acceder a los objetos visuales añadidos a la lista tengo que utilizar getChildAt o getChildByName
<code>trace("Accediendo con getChildAt :: =" + simb0.getChildAt(1).name); //traze simb3
trace("Accediendo con getChildByName :: =" + simb0.getChildByName("simb3").x); //traze 30</code>
Pero si ahora metemos otro nivel, otro objeto dentro de este, teniendo dos subniveles:
<code>var simb4:simbolo = new simbolo();
simb4.x=60;
simb4.name="simb4";
simb3.addChild(simb4);</code>
No me deja encadenar getChildAt o getChildByName para llegar a el!!
<code>trace("Accediendo con getChildByName :: =" + simb0.getChildByName("simb3").getChildByName("simb4").name);
//traza = 1061: Call to a possibly undefined method getChildByName through a reference with static type flash.display:DisplayObject.</code>
Pero si que me deja acceder si lo hago en dos tiempos
<code>var ruta1:Object=simb0.getChildByName("simb3");
trace(ruta1.getChildByName("simb4").name); //Traza correctamente simb4</code>
//Tambien encontre esta forma que funciona
<code>var cont:Object=DisplayObjectContainer(simb0).getChildByName("simb3");
trace("cont="+cont.name);
//traza correctamente simb3
var cont2:Object=DisplayObjectContainer(simb3).getChildByName("simb4");
trace("cont="+cont2.name);</code>
Con lo que te ahorras rutas largas de puntos accediendo directamente al ultimo objeto contenedor. Es correcto sustituir el metodo de ruta por puntos por este metodo?
FINALIZANDO 1
Entonces, para trabajar con los clips visuales lo correcto es acceder directamente al objeto, no al añadido a la lista con rutas o utilizar el estilo de mis ultimas lineas por tiempos ?
Juga
Ui, y se me olvidaba...(joer, q trocho de post no? Espero que alguno lo 'intente leer' aunque no de ganas... XD)
Mi última pregunta es, si no existe el root y por ejemplo quieres definir dentro de una instancia de una clase que acceda a algo que has colocado en el root, usea, en la linea de tiempo principal, como puedes accedes?
Ej:
Si hemos colocado los clips del ejemplo anterior en la linea de tiempo principal:
<code>var simb0:simbolo = new simbolo();
addChild(simb0);
simb0.name="simb0";
var simb1:simbolo = new simbolo();
simb1.x=60;
simb1.name="simb1";
addChild(simb1);
var simb3:simbolo = new simbolo();
simb3.x=30;
simb3.name="simb3";
simb0.addChild(simb3);</code>
Como accedemos a simb0, simb1 o simb3 desde una clase?
Antes, desde as2, directamente podiamos poner _root.simb0 y te la pillaba, pero ahora no funciona porq root no existe.
Tb he mirado de esta forma:
<code>var cont4:Object=DisplayObjectContainer(root).getChildByName("simb0");
trace("cont stage="+cont4.name)</code>;
Que funciona correctamente si esta en la linea de tiempo principal pero no cuando esta dentro de una clase:
Clase externa:
<code>package {
public class miClase {
public function miClase() {
var cont4:Object=DisplayObjectContainer(root).getChildByName("simb0");
trace("cont stage="+cont4.name);
}
}
}</code>
En la linea de tiempo principal creo una instancia de la clase:
<code>var laClase:miClase=new miClase();</code>
y traza estos errores:
1180: Call to a possibly undefined method DisplayObjectContainer.
1120: Access of undefined property root.
Ave si alguien puede contestarme estas dudas hiperbasicas de as3!!
Mil gracias por adelantado
Usuario desconocido
Joer que tocho de post xD
Mi consejo, pillate el libro Essential ActionScript 3.0 by Colin Moock y olvidate de una vez por todas de _root :)
Ventd'Aval
yo la verdad intentaria evitar el uso de getChilds (yo lo veo tan guarro como usar _root... en la mayoria de los casos, vamos ^^)...
La idea en AS3 es que los clips y/o metodos se deberian mantener como variables y "llevarlas" (premeditadamente) a las clases externas, clips, modulos, componentes, etc... de esta manera se asegura que las aplicaciones funcionan de manera mas modular, y cada clase/modulo/componente funciona de forma independiente, interactuando con otros sólo usando metodos y propiedades controladas y premeditadas...
Es decir, usando tu ejemplo de la clase externa:
<code>class clase {
function clase(miclip:MovieClip) {
trace("Desde clase: simb3._x="+miclip._x);
}
}</code>y luego desde tu api:<code>
var clip1b=new MovieClip();
mipadre.addChild(clip1b);
var miClase:clase=new clase(clip1b); </code>
Ahora, la clase MovieClip tiene la particularidad de ser dinamica, por lo que en principio podriamos hacer esto:<code>var padre=new MovieClip();
padre.hijo1=new MovieClip();
padre.hijo2=new MovieClip();</code>
y luego ya enviar "padre" a una clase, y acceder a sus hijos usando la notacion de puntos. Pero esto es bastante chapuzas, ya que estas declarando propiedades publicas de una clase en runtime (es recomendable no hacerlo)... pero la idea es mas o menos la misma que lo anterior... estamos declarando que "hijo1" e "hijo2" son propiedades publicas de la instancia "padre" de la clase MovieClip.
Ah, y justamente ayer Adobe publico gratuitamente dos capitulos del libraco ese de Moock, y uno de ellos trata justamente sobre la Display List:
http://www.moock.org/blog/archives/000254.html
Saludos...
Juga
Si, ya tengo el libro de MOOCK, estoy repasandolo junto al manual de adobe, pero queria asegurarme de algunas cosas XD
Gracias Ventd'Aval (sobretodo por la rapidez), ese metodo lo habia utilizado, pasarle las instancias creadas para que puedan comunicarse varias instancias, pero me parecia un poco raro hacerlo así, ya que si quieres que tu instancia se actualize o comunique con otras dos de diferente clase tendrias que mandarselas, y si quieres que se comunique con 10 mandar las 10...
Y respecto a la comunicación entre clases? Es posible que una instancia de una clase tenga una funcion que mande algun dato o llame a algun evento a otra clase de forma que esta modifique todas las instancias creadas?
Por ejemplo:
Tienes una clase que se llama emisor y 3 clases que se llaman receptor1, receptor2 y receptor3 y queremos que emisor tenga una funcion que envie un valor a todas las instancias creadas de receptor1, receptor2 y receptor3. Esto se hace con el tema de evenDispatcher? o con subclases o extendiendo la clase emisor?
Bueno, voy a seguir leiendo el libro de Moock, ave si me aclaro... XD
Ventd'Aval
Juga
Gracias Ventd'Aval (sobretodo por la rapidez), ese metodo lo habia utilizado, pasarle las instancias creadas para que puedan comunicarse varias instancias, pero me parecia un poco raro hacerlo así, ya que si quieres que tu instancia se actualize o comunique con otras dos de diferente clase tendrias que mandarselas, y si quieres que se comunique con 10 mandar las 10...
Yo no soy un gran experto en OOP, pero yo creo que estas buscando una solucion demasiado universal para algo demasiado ambiguo... osea, buscas un _root :P
Puedes usar, como dices, emisores y receptores, puedes usar un array de objetos, un objeto de arrays, un diccionario, una clase que mantenga tu display list, etc etc etc...
Al final yo te recomendaria que te pongas a hacer cosillas y vayas viendo como queda mejor en cada caso... al final estas cosas se terminan haciendo de muy diferentes maneras dependiendo de las circunstancias y de la logica de la aplicacion.
Saludos...
Juga
Al final, testeando y testeando con clases, clips y historias he llegado a una pequeña solución a mis dudas.
El tema es que necesitaba que de alguna forma algunas clases pudieran acceder a algunas instancias o clips de la pelicula y me parecia un poco sucio enviar y guardar esa informacion en cada instancia cuando la crearas dado a que se iban a crear muchisimas instancias.
Ademas, estos clips e instancias deberian ser accesibles facilmente en casi todas las clases creadas.
Y mirando y mirando he leido como funcionan las variables y funciones de una clase cuando los defines como static
De forma que lo he solucionado todo creando una clase a la que podria llamar rutas y en la cual se van almacenando las rutas como variables estaticas en plan: private static var ruta1:Object; a las cuales puedo acceder desde cualquier clase o cualquier lugar de la aplicacion con:
ruta.ruta1;
De esta forma tendria la clase:
<code>package {
public class ruta {
public static var __root:Object;
public function ruta() {
}
public static var configuracion=function (mc:Object) {
__root=mc;
};
}
}</code>
Una clase que testearia si llega a los datos desde esta:
<code>package {
import flash.utils.*;
import ruta;
public class clase2 {
public function clase2() {
trace("desde clase= "+ruta.__root.name);
}
}
}</code>
Y en la linea de tiempo principal:
<code>import ruta;
import clase2;
//
var simb0:Sprite = new Sprite();
addChild(simb0);
simb0.name="correcto";
//
ruta.configuracion(simb0);
trace("desde root= "+ruta.__root.name);
//traza desde el constructor de la clase
var nc:clase2=new clase2();</code>
ASi que en cualquier sitio que quiera acceder al clip simb0 tendre que importar la clase y poner ruta.__root;
Que tal así? Correcto, chapuza o muy chapuza?