Actionscript 3 compare two MovieClips - actionscript-3

I dynamically add MovieClips to an DisplayObjectContainer. Some of these MovieClips loop through all children of DisplayObjectContainer to check gravitation and collision. Though, when I check if the current child is not equal to the caller MovieClip it seems to check the type only.
So basically, when I check MovieClip equality it seems to check the type only.
Main.as:
var planet:Planet = new Planet(holder);
planet.x = 0;
planet.y = 0;
planet.spawn();
var planet2:Planet = new Planet(holder);
planet2.x = 50;
planet2.y = 50;
planet2.spawn();
Planet.as:
public class Planet {
public var x:Number = 0;
public var y:Number = 0;
private var _holder:DisplayObjectContainer;
private var _mc:MovieClip;
public function Planet(holder:DisplayObjectContainer) {
_holder = holder;
_mc = new PlanetMovieClip();
_mc.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
public function spawn():void {
_holder.addChild(_mc);
}
private function enterFrameHandler(evt:Event):void {
for(var i:int = 0; i < _holder.numChildren; i++) {
var child:MovieClip = _holder.getChildAt(i) as MovieClip;
// the other planet never passes this check
if(child !== _mc) {
trace('child is not the same');
}
}
}
}
So am I doing something wrong, should I approach an other method or should I just add an property that generates a random token used for identification?

you should remove as MovieClip; in _holder.getChildAt(i);

I would change !== with !=
The rest of your code seems ok.

First of all you have error in the code you have given to create Planet movieclip.
It should be
var planet:Planet = new Planet(holder);
planet.x = 0;
planet.y = 0;
planet.spawn();
var planet2:Planet = new Planet(holder)
planet2.x = 50;
planet2.y = 50;
planet2.spawn();
Did you check for null in Planet.as ?
if(child!=null) {
if(child !== _mc)
trace('child is not the same');
else
trace("child same");
}
And ofcourse you can always assign some unique name to the movieclips, and use it for comparing.

Related

AS3 class : access of undefined method / property errors

I have this class :
package {
import flash.net.SharedObject;
import flash.display.DisplayObject;
public class gestioneMultilingua
{
public static function settaLingua(lingua:String):void
{
var dati:SharedObject = SharedObject.getLocal("datiApp", "/");
dati.data.lingua = lingua;
dati.flush();
}
public static function applicaFiltriLingua():void
{
var dati:SharedObject = SharedObject.getLocal("datiApp", "/");
var lingua : String = dati.data.lingua;
for(var i:int = 0; i<numChildren; i++){
var e:Object = getChildAt(i);
if(e.name.indexOf("$"+lingua) >= 0){
e.visible = true;
}
else if(e.name.indexOf("$") >= 0){
e.visible = false;
}
}
}
}
}
but I got these errors :
How can I fix them ? maybe I need to import a package ?
You can use a static function without any problem when you use it correctly of course, the problem here is not that the function is static (and not using numChildren or calling getChildAt() in that static function) but it is about how you did all that.
In your case, you want to work with a DisplayObjectContainer's children, so you can simply pass that object to your applicaFiltriLingua() function like this :
public static function applicaFiltriLingua(container:DisplayObjectContainer):void
{
var dati:SharedObject = SharedObject.getLocal("datiApp","/");
var lingua:String = dati.data.lingua;
for (var i:int = 0; i < container.numChildren; i++)
{
var e:DisplayObject = container.getChildAt(i);
if (e.name.indexOf("$" + lingua) >= 0) {
e.visible = true;
} else if (e.name.indexOf("$") >= 0) {
e.visible = false;
}
}
}
then you can call your function without any problem, like this, for example :
import gestioneMultilingua;
gestioneMultilingua.applicaFiltriLingua(this);
Hope that can help.
A static method can only make calls to another static method. numChildren and getChildAt are not static methods and calling them from inside a static method can only produce errors. Even if your class was extending a DisplayObjectContainer it will still get those errors since instances of that class will have getChildAt method and numChildren property but at static level those would still not exist and would still produce errors.
Do not make your applicaFiltriLingua method static and extend a valid DisplayObjectContainer
Since your function is a STATIC you can never instantiate one and non-static fields of all types are not allowed. Instance constructors are also not allowed and the class is automatically sealed.
Make method non-static and instantiate the class "gestioneMultilingua"
var multilingua:gestioneMultilingua = new gestioneMultilingua();
than you can access it like that multilingua.applicaFiltriLingua(//reference to stage)
and
do
public function applicaFiltriLingua(stage_ref:MovieClip):void
{
var dati:SharedObject = SharedObject.getLocal("datiApp", "/");
var lingua : String = dati.data.lingua;
for(var i:int = 0; i<numChildren; i++){
var e:Object = stage_ref.getChildAt(i);
if(e.name.indexOf("$"+lingua) >= 0){
e.visible = true;
}
else if(e.name.indexOf("$") >= 0){
e.visible = false;
}
}
}

how addChild is being used in below AS3 code?

For addChild(iconObject) (second line inside function startAmoebaAttack()), can anyone explain me where will iconObject be added in? because it doesn't have any object or array before addChild like iconObject.addChild(newSoldier);
private var iconObject:Sprite;
public function startAmoebaAttack() {
iconObject = new Sprite();
addChild(iconObject);
createSoldierIcon();
}
public function createSoldierIcon(){
soldierIcon = new Array();
for(var i:uint = 0; i<soldierLeft; i++){
var newSoldier:SoldierIcon = new SoldierIcon();
newSoldier.x = 65 + i *24;
newSoldier.y = 590;
iconObject.addChild(newSoldier);
soldierIcon.push(newSoldier);
}
}
It will automatically run it in this's context (same as this.addChild(iconObject)). In your case this is descendant of DisplayObjectContainer .

Actionscript3 how to get the index of object clicked

I'm trying to have this hero shoot the bullet. Ex: The bullet has fire and ice type. if the hero placed is fire type then it will shoot fire bullet, if it's ice type then it will shoot ice bullet. And each bullet have each own effects and damages.
So, I've tried to get the index of hero chosen and later on the index will be used to define which bullet used by tracing (heroesArray.indexOf(heroClicked)); but the value of heroclicked is (object Hero1). so I can't use it since the array of heroesArray is [hero1,hero2]. I did splitting and joining too but it kinda messed up...
My question is how to get the String value that only contains the variable of clicked object (hero1 or hero2)? Is there any 'vocabulary' to get the variable name like getqualifiedclassname used for getting class name of an object?
Or is there any other idea to create bullet type the same as hero type without using indexOf ?
Thanks !
Here is the code :
package {
import flash.display.MovieClip
import flash.events.MouseEvent
import flash.events.Event
import flash.display.Sprite
import flash.utils.*
public class Hero {
private var heroesArray:Array;
private var heroContainer:Sprite = new Sprite;
private var hero1:MovieClip = new Hero1();
private var hero2:MovieClip = new Hero2();
private var bulletArray:Array;
private var bullet1:MovieClip = new Bullet1();
private var bullet2:MovieClip = new Bullet2();
private var moveHero:Boolean = false;
private var movingHero:MovieClip;
private var _money:Money = new Money();
private var _main:Main;
private var _enemy:Enemy = new Enemy(_main);
public function Hero(main:Main)
{ _main = main;
heroesArray = [hero1,hero2];
bulletArray = [bullet1,bullet2];
}
private function playerMoving(e:Event):void
{
if (moveHero == true)
{
movingHero.x = _main.mouseX;
movingHero.y = _main.mouseY;
}
}
private function chooseHero(e:MouseEvent):void
{
var heroClicked:MovieClip = e.currentTarget as MovieClip;
var cost:int = _main._money.money ;
if(cost >= 10 && moveHero == false)
{
_main._money.money -= 10;
_main._money.addText(_main);
moveHero = true;
var heroClass:Class = getDefinitionByName(getQualifiedClassName(heroClicked)) as Class;
movingHero = new heroClass();
heroContainer.addChild(movingHero);
movingHero.addEventListener(MouseEvent.CLICK, placeHero);
}
}
private function placeHero(e:MouseEvent):void
{
var heroClicked:MovieClip = e.currentTarget as MovieClip;
var heroRow:int = Math.floor(_main.mouseY/75);
var heroCol:int = Math.floor((_main.mouseX-10)/65);
if(heroRow>0 && heroCol>0 && heroRow<6 && heroCol<10&&
_main.field[heroRow][heroCol]==0)
{
movingHero.fireRate =75;
movingHero.recharge = 0;
movingHero.firing = false;
movingHero.heroRow = heroRow;
movingHero.x = 42+heroCol*65;
movingHero.y = 10+heroRow*75;
_main.field[heroRow][heroCol]=1;
moveHero = false;
movingHero.removeEventListener(MouseEvent.CLICK, placeHero);
}
}
public function displayHero(stage:Object):void
{
stage.addChild(heroContainer);
for (var i:int = 0; i<2;i++)
{
stage.addChild(heroesArray[i]);
heroesArray[i].x = 37;
heroesArray[i].y = 80+i*70;
heroesArray[i].width=60;
heroesArray[i].height=55;
heroesArray[i].buttonMode = true;
heroesArray[i].addEventListener(MouseEvent.CLICK, chooseHero);
heroesArray[i].addEventListener(Event.ENTER_FRAME, playerMoving);
}
}
}
}
You've pretty much got the answer right in front of you. The two heros are of classes Hero1 and Hero2, and you find the class via
var heroClass:Class = getDefinitionByName(getQualifiedClassName(heroClicked)) as Class;
All you need to do is compare heroClass to those two classes like so:
if(heroClass == Hero1)
{
...
}
else
{
...
}
Linking hero to bullet type
If you don't know, or don't want to learn classes (see my comment for an excellent tutorial) then you'll need a lookup table/Dictionary so that you can link bullet type to hero.
//Put this in your constructor after the bullet types and heroes have been declared
var bulletDict = new Dictionary();
bulletDict[hero1] = bulletTypeIce; //Note the lack of quotations around hero1 and 2
bulletDict[hero2] = bulletTypeFire;
So, to get the bullet type out:
var bulletType = bulletDict[heroClicked];

How to remove all of one class of children from screen in Flash CS4 AS3?

Ok, so I've been stuck on this for about three hours now and I finally feel like asking for help.
Basically, I am trying to remove all instances of an enemy object from the screen when my player ship makes contact with one of them, as he then loses a life and is put back into a safe position on the screen.
EDIT: This is all the code from my Enemy Dude .as file, a bit overboard maybe but nonetheless.
package
{
import flash.display.MovieClip;
import flash.events.*;
import flash.media.Sound;
import flash.media.SoundChannel;
public class Enemydude extends MovieClip
{
private var _root:Object;
private var speed:int = 6;
private var shipps = this
public function Enemydude()
{
addEventListener(Event.ADDED, beginclass);
addEventListener(Event.ENTER_FRAME, entFrame);
}
private function beginclass(event:Event):void
{
_root = MovieClip(root);
}
private function entFrame(event:Event):void
{
x -= speed;
if(this.x < -64)
{
removeEventListener(Event.ENTER_FRAME, entFrame);
_root.removeChild(this)
}
if(_root.gameover)
{
x = -700
removeEventListener(Event.ENTER_FRAME, entFrame);
removeEventListener(Event.ADDED, beginclass);
}
for (var i:int = 0; i<_root.playerBulletContainer.numChildren; i++)
{
var bulletTarget:MovieClip = _root.playerBulletContainer.getChildAt(i)
if (hitTestObject(bulletTarget))
{
removeEventListener(Event.ENTER_FRAME, entFrame);
_root.removeChild(this);
_root.playerBulletContainer.removeChild(bulletTarget);
bulletTarget.removeListeners();
_root.Score += 10
makeExplosion();
}
}
if(hitTestObject(_root.mcship))
{
makeExplosion();
shipPos();
removethis();
}
}
private function makeExplosion()
{
var sndExplode:snd_explosion1;
var sndExplodeChannel:SoundChannel;
sndExplode=new snd_explosion1();
sndExplodeChannel=sndExplode.play();
var newExplosion01:explosionEffect=new explosionEffect ;
newExplosion01.x=this.x;
newExplosion01.y=this.y;
_root.explosionContainer.addChild(newExplosion01);
}
private function shipPos()
{
_root.lives -= 1;
_root.mcship.x = 80;
_root.mcship.y = 225;
for each(var i:Enemydude in _root.enemies)
{
removethis();
}
_root.enemies.length = 0;
}
public function removethis():void
{
if(parent) parent.removeChild(this)
removeEventListener(Event.ENTER_FRAME, entFrame);
}
}
}
EDIT: And this is the code I now have that relates to the Enemydude in my main timeline, quite sorry about all this.
var enemies:Array = [];
var Shipheight:Number = 300;
var Enemytime:int = 0;
var Enemylimit:int = 16;
if (Enemytime<Enemylimit)
{
Enemytime ++;
}
else
{
var newEnemy01 = new Enemydude();
newEnemy01.y = Shipheight;
newEnemy01.x = stage.stageWidth + 64;
addChild(newEnemy01);
enemies.push(newEnemy01);
Enemytime = 0
function shipY(event:Event):void
{
Shipheight = Math.ceil(Math.random()* 250) + 80;
}
Thank you for your help in advance, any advice is appreciated.
I suggest storing your enemies in an Array.
For example, create the array enemies:
var enemies:Array = [];
And then amend your code to:
else
{
var newEnemy01 = new Enemydude();
newEnemy01.y = Shipheight;
newEnemy01.x = stage.stageWidth + 64;
addChild(newEnemy01);
enemies.push(newEnemy01);
Enemytime = 0;
}
That way you can remove all of the enemies using this new array:
for each(var i:Enemydude in enemies)
{
i.remove(); // Or whatever function Enemydude has to remove itself.
}
// Empty the enemies Array.
enemies.length = 0;
Here's the .remove() method you could make for Enemydude:
public function remove():void
{
if(parent) parent.removeChild(this);
// Remove any event listeners etc from this object.
}
A common and easy way of doing this is to create a subcontainer to hold the objects and destroy this object instead. It makes easy for some collision checks too, since you can use the holder object to make one check against the player.
If you don't want to create this, you can use an array or a vector to store references to this objects, what makes easy to traverse the list.
I persoally recommend the vector aprouch:
var enemyList:Vector.<Enemy> = new Vector.<Enemy>();
Then you can loop almost like an array (as Marty Wallace showed on his answer):
for each(var e:Enemy in enemyList) {
container.removeChild(e);
}
enemyList.length = 0; // empty vector
Vectors are a bit slower than normal arrays, but are type safe. The difference in performance is almost negligible in most cases.

How to pass a variable into an Event.COMPLETE function?

I am running a loop to pull thumbs into a containing movieclip from an xml list. What I want to do is have the thumb's parent movieclip fade in after they are done loading, but I can't figure out how to reference the parent once it's loaded.
My code(which currently doesn't work the way I want it):
var vsThumb:articleBox;
var currentarticleX:Number = 0;
var articleLinkURL:String;
var articleImageURL:String;
var articleText:String;
var vsThumbLoader:Loader;
var next_x:Number;
next_x = 9;
var thumbAlphaTween:Tween;
var articlevsThumb:Array = new Array();
function loadarticleHeadlines():void
{
for (var i:int = 0; i < egarticleXml.articlelist.articleitem.length(); i++)
{
vsThumb = new articleBox();
vsThumb.alpha = 0;
vsThumbLoader = new Loader();
vsThumbLoader.load(new URLRequest(egarticleXml.articlelist.articleitem[i].articlethumbnail));
articleListContainter.addChild(vsThumb);
vsThumb.articleImage.addChild(vsThumbLoader);
vsThumb.articleTitle.text = egarticleXml.articlelist.articleitem[i].articletitle;
titleAutosize(vsThumb.articleTitle);
vsThumb.x = next_x;
next_x += 260;
articlevsThumb[i] = vsThumb;
vsThumbLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, showBox);
vsThumb.clickBtn.buttonMode = true;
}
function showBox(event:Event):void
{
thumbAlphaTween = new Tween(articlevsThumb[i],"alpha",None.easeNone,0,1,.25,true);
}
}
So how do I refer back to the loader's parent so I can fade in the whole movieclip? Can I pass a variable into the showBox function?
Don't use nested functions. They tend to make things more complicated.
i will always have the end value (articleitem.length()-1) in all of the event handlers you create, because its scope is the outer function, loadarticleHeadlines (it will increase by 1 on every iteration). That's probably why your code doesn't work.
The event will be fired on the loaderInfo of your loader, so you can find the loader's parent by using event.target.loader.parent:
function loadarticleHeadlines() : void
{
for (var i:int = 0; i < egarticleXml.articlelist.articleitem.length(); i++)
{
vsThumb = new articleBox();
vsThumb.alpha = 0;
vsThumbLoader = new Loader();
vsThumbLoader.load(new URLRequest(egarticleXml.articlelist.articleitem[i].articlethumbnail));
articleListContainter.addChild(vsThumb);
vsThumb.articleImage.addChild(vsThumbLoader);
vsThumb.articleTitle.text = egarticleXml.articlelist.articleitem[i].articletitle;
titleAutosize(vsThumb.articleTitle);
vsThumb.x = next_x;
next_x += 260;
articlevsThumb[i] = vsThumb;
vsThumbLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, showBox);
vsThumb.clickBtn.buttonMode = true;
}
}
function showBox(event:Event):void
{
thumbAlphaTween = new Tween(event.target.loader.parent,"alpha",None.easeNone,0,1,.25,true);
}
You don't need to pass a variable to your showBox, use the target property of the Event to retrieve the Loader:
function showBox(event:Event):void
{
var li:LoaderInfo=LoaderInfo(event.target);
// be nice remove your listener when your are done
li.removeEventListener(Event.COMPLETE, showBox);
var ldr:Loader=li.loader; // here is your loader
// do whatever you want with loader
thumbAlphaTween = new Tween(articlevsThumb[i],"alpha",None.easeNone,0,1,.25,true);
}