Comunidad de diseño web y desarrollo en internet online

Problema con removeChild

Citar            
MensajeEscrito el 16 Ene 2010 08:31 am
Bueno primero que nada un gran saludo ^^ para todos aquellos que estan leyendo esto, bueno estoy aprendiendo As3
y me empiezo a familiarizar con los cambios que tiene con respecto a As2.

Bueno el problema es el siguiente:

En el escenario tengo una instancia (MC) llamado carro.
Tengo un unico frame donde esta todo el script, en el hago que "carro" se mueva en el eje y, y con un Timer hago que cada cierto tiempo el "carro" dispare (usando addChild , en la biblioteca tengo un solo objeto llamado bala).

Y a la hora de eliminar la bala del escenario, la primer bala si se elimina bien, pero de la segunda hasta la 'n' bala tambien se eliminar solamente que me marca un error:

ArgumentError: Error #2025: El objeto DisplayObject proporcionado debe ser un elemento secundario del llamador.
at flash.display::DisplayObjectContainer/removeChild()
at Disparos_fla::MainTimeline/fuego()


Y no entiendo porque me marca dicho error, ya probe con un cast (DisplayObject,MovieClip) y nada, este es el codigo que tengo en mi frame.

Código ActionScript :

var volver:Boolean=true;
var dis:Timer=new Timer(1000);
var b:Array=new Array();
var i,j:int;
i=0;
j=0;

dis.start();

dis.addEventListener(TimerEvent.TIMER,disparar);

function disparar(e:TimerEvent):void{
   b[i]=(new bala());
   b[i].x=carro.x+10;
   b[i].y=carro.y;
   b[i].name=i;
   addChild(b[i]);
   b[i].addEventListener(Event.ENTER_FRAME,fuego);   
   i++;
}

function fuego(e:Event):void{
   if(e.target.x>300){
      j=int(e.target.name);
      trace(e.target.name+"   "+(j));
      removeChild(b[j]);
   }
   else{
      e.target.x+=15;
   }
}

//De aqui para abajo es para hacer mover la instancia carro sobre el eje y
carro.addEventListener(Event.ENTER_FRAME,moverse);

function moverse(e:Event):void{
 if((e.target.y<300)&&(volver)){
   e.target.y+=5;
 }
  else{
    e.target.y-=5; 
    volver=false;
  }
  
   if((e.target.y>30)&&(!volver)){
   e.target.y-=5;
 }
  else{
    e.target.y+=5; 
    volver=true;
  }
   
}


Espero que me puedan orientar con este problemita,y de antemano muchas gracias. :)

Por Deivtox

72 de clabLevel



Genero:Masculino  

Estudiante

firefox
Citar            
MensajeEscrito el 16 Ene 2010 05:03 pm
intenta haciendo cast de tu clase bala .. por ejemplo:

Código ActionScript :

removeChild(bala(b[j]));


identifica las clases con la primera letra en mayuscula Bala, Bullet, etc

Jonathan

Por maneuver

243 de clabLevel



Genero:Masculino  

Mexico City

firefox
Citar            
MensajeEscrito el 17 Ene 2010 07:17 am
@jn_Flash, acabo de probar lo de hacer cast con la clase bala, pero me sigue marcando este mismo error.

ArgumentError: Error #2025: El objeto DisplayObject proporcionado debe ser un elemento secundario del llamador.
at flash.display::DisplayObjectContainer/removeChild()
at Disparos_fla::MainTimeline/fuego()


Visualmente parece ser que si se remueven porque al llegar al limite del eje x desaparece y al momento de desaparecer me marca este error por cada objeto que remuevo (hablando del objeto tipo bala)

Por Deivtox

72 de clabLevel



Genero:Masculino  

Estudiante

firefox
Citar            
MensajeEscrito el 17 Ene 2010 10:01 am
Hola,
veo 2 problemas:
- El primero es que creas un listener para cada bala, pero no lo eliminas cuando haces el removeChild.
- El segundo es que en las funciones de los listener tienes que especificar de alguna forma que e.target es un MovieClip (haciendo un casting para que el compilador pueda comprender que tu e.target tiene las propiedades y métodos de los MovieClip) y de ese modo no te hará falta crear la propiedad "name" de las balas, ni usar las variables "i" y "j".
Yo reescribiría tu código así:

Código ActionScript :

var volver:Boolean = true;
var dis:Timer = new Timer(1000);
var b:Array = new Array();

dis.start();
dis.addEventListener(TimerEvent.TIMER, disparar);

function disparar(e:TimerEvent):void
{
   var newBala:bala = new bala();
   newBala.x = carro.x + 10;
   newBala.y = carro.y;
   addChild(newBala);
   newBala.addEventListener(Event.ENTER_FRAME, fuego);
   b.push(newBala);
}

function fuego(e:Event):void
{
   var balaMC:MovieClip = e.target as MovieClip;
   if (balaMC.x > 300)
   {
      //Hay que eliminar el listener de la bala:
      balaMC.removeEventListener(Event.ENTER_FRAME, fuego);
      removeChild(balaMC);
   }
   else
   {
      balaMC.x += 15;
   }
}

//De aqui para abajo es para hacer mover la instancia carro sobre el eje y
carro.addEventListener(Event.ENTER_FRAME, moverse);

function moverse(e:Event):void
{
   var carroMC:MovieClip = e.target as MovieClip;
   if ((carroMC.y < 300) && volver)
   {
      carroMC.y += 5;
   }
   else
   {
      carroMC.y -= 5;
      volver = false;
   }

   if ((carroMC.y>30) && !volver)
   {
      carroMC.y -= 5;
   }
   else
   {
      carroMC.y += 5;
      volver = true;
   }
}

Por isidoro

Claber

498 de clabLevel

2 tutoriales

Genero:Masculino  

firefox
Citar            
MensajeEscrito el 18 Ene 2010 02:15 am

isidoro escribió:

Hola,
veo 2 problemas:
- El primero es que creas un listener para cada bala, pero no lo eliminas cuando haces el removeChild.
- El segundo es que en las funciones de los listener tienes que especificar de alguna forma que e.target es un MovieClip (haciendo un casting para que el compilador pueda comprender que tu e.target tiene las propiedades y métodos de los MovieClip) y de ese modo no te hará falta crear la propiedad "name" de las balas, ni usar las variables "i" y "j".
Yo reescribiría tu código así:

Código ActionScript :

var volver:Boolean = true;
var dis:Timer = new Timer(1000);
var b:Array = new Array();

dis.start();
dis.addEventListener(TimerEvent.TIMER, disparar);

function disparar(e:TimerEvent):void
{
   var newBala:bala = new bala();
   newBala.x = carro.x + 10;
   newBala.y = carro.y;
   addChild(newBala);
   newBala.addEventListener(Event.ENTER_FRAME, fuego);
   b.push(newBala);
}

function fuego(e:Event):void
{
   var balaMC:MovieClip = e.target as MovieClip;
   if (balaMC.x > 300)
   {
      //Hay que eliminar el listener de la bala:
      balaMC.removeEventListener(Event.ENTER_FRAME, fuego);
      removeChild(balaMC);
   }
   else
   {
      balaMC.x += 15;
   }
}

//De aqui para abajo es para hacer mover la instancia carro sobre el eje y
carro.addEventListener(Event.ENTER_FRAME, moverse);

function moverse(e:Event):void
{
   var carroMC:MovieClip = e.target as MovieClip;
   if ((carroMC.y < 300) && volver)
   {
      carroMC.y += 5;
   }
   else
   {
      carroMC.y -= 5;
      volver = false;
   }

   if ((carroMC.y>30) && !volver)
   {
      carroMC.y -= 5;
   }
   else
   {
      carroMC.y += 5;
      volver = true;
   }
}
@isidoro el consejo que me haz provisto resulto ser la solución a dicho problema :D , ciertamente tengo mucho que aprender de As3, ahora comprendo que al eliminar una instancia si tiene alguna funcion activada por evento tengo que eliminarla, muchisimas gracias.

Mi problema ha sido solucionado. :cool:

Por Deivtox

72 de clabLevel



Genero:Masculino  

Estudiante

firefox
Citar            
MensajeEscrito el 18 Ene 2010 11:29 am
Hola de nuevo,
espero que leas este mensaje, porque en el código que puse falta algo importante. Justo debajo de removeChild(balaMC); tienes que añadir:

Código ActionScript :

b.splice(b.indexOf(balaMC), 1);

Sino tu array seguirá almacenando las balas incluso después de que hayan desaparecido.
De todos modos, me imagino que la utilidad del array "b" es la de almacenar las balas que hay en pantalla para comprobar mediante un bucle for si tu personaje colisiona con alguna de ellas. Otra forma de hacer esto sería no usar ese array "b", y haciendo que cada bala sea la que compruebe si colisiona o no con el personaje (aunque las 2 formas de hacerlo son válidas).

Por isidoro

Claber

498 de clabLevel

2 tutoriales

Genero:Masculino  

firefox
Citar            
MensajeEscrito el 18 Ene 2010 05:27 pm
OK, acabo de leer el post, y ya cheque la linea de codigo que mandaste, tienes razon, mientras se sigan creando balas el tamaño del array crecera pero mantiene los lugares de las balas ya eliminadas, y con el splice lo que hace es eliminar esos lugares para solo quedarme con las balas validas aun.

Tambien habia hecho primero la creacion de las balas sin necesidad del array, pero igual tenia problemas, de todas formas lo volvere a checar, y te agradezco la ayuda :) muchas gracias.

Por Deivtox

72 de clabLevel



Genero:Masculino  

Estudiante

firefox

 

Cristalab BabyBlue v4 + V4 © 2011 Cristalab
Powered by ClabEngines v4, HTML5, love and ponies.