AS3 removing all children from array in a class from parent class - actionscript-3

In the Level 1 class (Parent) I generate citizens as seperate objects (c) to walk from left or right across the stage. all of these get added to an array called citizens:
if (citizens.length < 10)
{
// create citizen
var c:Citizen = new Citizen(side,speed,yPos);
addChildAt(c, 2);
citizens.push(c);
}
I want to remove each instance of the class and also remove the event listener that is attached to it in the class:
this.addEventListener(Event.ENTER_FRAME,moveCitizen);
Would I use a for each then splice from the array? E.G
for each (c in citizens) {
removeEventListener(Event.ENTER_FRAME,moveCitizen);
splice();
}

You could do something similar to the following:
// Creation
if (citizens.length < 10) {
// create citizen
var c:Citizen = new Citizen( side, speed, yPos );
addChildAt( c, 2 );
citizens.push( c );
}
// Removal
for( var i:int = 0; i < citizens.length; i++ ) {
var c:Citizen = citizens[ i ].pop();
removeChild( c )
c.cleanUp();
}
// In Class Citizen
public function cleanUp():void {
removeEventListener( Event.ENTER_FRAME, moveCitizen );
}

#user1878381 you have to make one method in citizens class if you needed to call in every object say reset(). when you removed a object you must call reset function of that object which reset the citizes by removing all eventlistner and reset all property of citizens in that object.
you can use array.pop() method to popout a latest pushed object from array by for each looping. if you are using array then array have many functionality like shift, pop, splice(i,1). etc...
i think for each is the best one among all..

Related

How to give differents directions of bullets on one array?

im very new on javascript, i was doing a ship gaming that you have to kill some asteroids, and when you take some differents of "objects" on the screen we expand our number of bullets. Okey, going to the point i could get 3 bullets on the screen when you take diffirents objects, but now i want to give 2 of that 3 bullets of the array different directions. When i tried, i have the problem that i give the 3 bullets the same direction, i know why but im for at least 5hrs trying to fix this and i cant.
Im programming on Flash Builder 4.7 with different classes, i ll give the code of the array who is in the main, and the bullet class so as the hero class too.
Main Array
public function evUpdateBullet():void//here execute update of my class Bullets
{
var i:int;
for(i=myBullets.length-1; i >= 0; i--)
{
if(myBullets != null) //to be ?
{
if(myBullets[i].isDestroyed) //is destroyed Bullets?
{
myBullets[i] = null;
myBullets.splice(i, 1); //deleted elements.
}else
{
myBullets[i].evUpdate();
}
}
}
}
here i push the array and create the bullet, remember myBullets is the name of the array.
public function evShoot(posX:int, posY:int):void//here create the bullet and push in the array
{
attack1 = new Bullet;
attack1.Spawn(posX, posY);
myBullets.push(attack1);
}
here i show the Hero code, where i define the position of the bullet is going to spawn on the screen.
if (isPressing_Shoot && !isDestroyed)// Here execute the event shoot without power
{
Main.instace.evShoot(model.x, model.y);
isPressing_Shoot = false;
canShoot = false;
}
evDestroyed();
}
here is the code from Bullet class
first the spawn
public function Spawn(posX:int, posY:int):void
{
isDestroyed = false;//first parameter of my bullet
model = new MCbullet;
Main.layer1.addChild(model);//painting the hero in the stage
model.x = posX;//position in the stage wiht the hero
model.y = posY;
model.tigger.visible = false;
}
then the Update
public function evUpdate():void//here conect with update general
{
if (model != null)//to be?
{
model.y -= 12;//move of my bullet
//model.x -= 12;
if (model.y <= 0 )
{
evDestroyed();
}
}
}
in this update i set the movement of y, so i can shoot vertically, but.. when i try to add an x.move, i do for the all array, so i want to know how i can give different move, for differents bullets of the same array.
Iterate through the array elements. There are a few ways to do this, but the one I'm most accustomed to using would be the for loop. It looks like this:
// loop through myBullets array to update
// each x and y position dependent on unique
// property value _xSpeed and _ySpeed.
for (var i:int = 0; i < myBullets.length; i++)
{
myBullets[i].x += myBullets[i]._xSpeed;
myBullets[i].y += myBullets[i]._ySpeed;
}
Obviously, you will need the _xSpeed and _ySpeed properties of the array elements to be set to dynamic values. You would first need to give the bullet class these properties and then set their values when you instantiate the bullets. That might look something like this:
function makeBullet():void{
var b:Bullet = new Bullet();
b.x = hero.x;
b.y = hero.y;
b._xSpeed = hero._xSpeed; // or put here whatever makes sense for assigning the right value in your application
And in your bullet class constructor, before the function but inside the class brackets, add the property:
var _xSpeed:Number = 0;
var _ySpeed:Number = 0;
Basically this is allowing each bullet to hold it's own special property that is independent of any other instance of the class.
I hope that helps.

AS3 + Starling - Find Unknown Sprite

I have legacy code project. While Starling is running sometimes some Sprite appears and covers all application.
In pure flash I used "console" https://code.google.com/p/flash-console/wiki/GettingStarted to get object hierarhy in display tree. But it doesn`t work for Starling.
My idea is to add some listener to root, cause this Sprite is in display list tree.
And find who is this Spite's parent.
Is it possible?
And find who is this Spite's parent. Is it possible?
If you are trying to find a display object, and you have no idea where it is coming from, one thing you could try doing is in a frame event, keep track of all the new sprites that are added to the display list. Then you can work backwards from there. Eg.
// keep track of unique display objects
private var _displayList:Array = [];
public function Main()
{
addEventListener( Event.ENTER_FRAME, trackDisplayList );
}
private function trackDisplayList( event:Event ):void
{
trackAsset( stage );
}
private function trackAsset( asset:* ):void
{
var i:int = -1;
while( ++i < asset.numChildren )
{
var child:* = asset.getChildAt( i );
if ( _displayList.indexOf( child ) == -1 )
{
_displayList.push( child );
trace( "tracking display object: " + child.name );
}
if ( child.numChildren > 0 )
{
trackAsset( child );
}
}
}
Hopefully you don't have a boat load of sprites to sort through! This is one way you could recursively check all your unique display objects.

actionscript removing movieclip children

Ive got a document class in this class I dynamically create movie clips, store them in an array and finally add it to the stage using addChild. That's all fine, the issue is though im trying to remove the movieClips through the array and it is throwing an error:
1034: Type Coercion failed: cannot convert []#26be1fb1 to flash.display.DisplayObject.
Here is my code:
// Note i have declared the array outside the function, so that's not an issue
function x (e:MouseEvent){
if (thumbnails.length !== 0){ // Determine if any movieclips have already been created on stage and delete them
for(var ctr:int = 0; ctr < thumbnails.length;ctr++ ){
removeChild(thumbnails[ctr]);
}
}
for (var i: int = 0;i < userIput; i++){ // Loop through and create instances of symbol
var thumb:Thumbnail = new Thumbnail();
thumb.y = 180; // Set y position
thumb.x = 30 + ((thumb.width + 10) * i);
addChild(thumb);
thumbnails[i] = [thumb]; // Add to array
}
}
When you retrieve the MovieClip from your Array, you need to cast it as a DisplayObject before attempting to remove it:
if (thumbnails.length !== 0){ // Determine if any movieclips have already been created on stage and delete them
for(var ctr:int = 0; ctr < thumbnails.length;ctr++ ){
removeChild(DisplayObject(thumbnails[ctr]));
}
}
Alternatively, you could consider using a Vector (a type-safe version of an Array) with the base-type set as DisplayObject:
var thumbnails:Vector.<DisplayObject> = new Vector.<DisplayObject>();
thumbnails.push(new MovieClip());
this.addChild(thumbnails[0]);
this.removeChild(thumbnails[0]);
For further reading, have a look at the Adobe documentation on type conversion and Vectors.
Update:
Instead of adding an instance of Thumbnail to your Array the following line is actually adding a further Array containing a single element to your thumbnails Array (in effect you are creating a multi-dimensional Array):
// You're assigning an array literal with a single element
// to this element of the the thumbnails array
thumbnails[i] = [thumb];
Try either of the following instead:
// What you meant
thumbnails[i] = thumb;
// Better
thumbnails.push(thumb);
The error that appears tells you that Flash Player cannot convert []#26be1fb1 to DisplayObject. The []#26be1fb1 gives you a hint what type of object at which address cannot be converted. [] is the type of object here that means the type Array so when removeChild() is called you try to pass an array to it, but the method expects DisplayObject.
Why this happens
Your code has a very simple but maybe unobstrusive problem, namely at this code line:
thumbnails[i] = [thumb]; // Add to array
You put your thumb into an array by using [] around thumb. So what your code actually is doing is that it adds an array with a single element (thumb) to the array thumbnails. After that you have an array of arrays with single elements.
Solution
Change the above line to:
thumbnails[i] = thumb; // Add to array
This should solve your issue.
For your perceived issue:
Use Vector instead of Array
or cast array item to Thumbnail class
But the main culprit will probably be the fact you never clear the items from the array, you remove them from the parent/stage, but you do not remove them from the array… together with adding the items at a specific place in the array will cause erratic behavior:
you add them:
t[0] = item0_0
t[1] = item0_1
t[2] = item0_2
t[3] = item0_3
then remove item0_0, item0_1, item0_2, item0_3 from stage, but leave them in the array
next you add e.g. 2 new ones
t[0] = item1_0
t[1] = item1_1
so you have:
on stage:
item1_0
item1_1
in array:
t[0] = item1_0
t[1] = item1_1
t[2] = item0_2
t[3] = item0_3
This should be working:
var thumbnails:Vector.<Thumbnail> = new Vector.<Thumbnail>();
function x (e:MouseEvent) {
var thumb:Thumbnail;
for each(thumb in thumbnails){
removeChild(thumb);
}
thumbnails = new Vector.<Thumbnail>(); // clear Vector by re-initiating it
for (var i: int = 0;i < userIput; i++){
thumb = new Thumbnail();
// ...
addChild(thumb);
thumbnails.push(thumb);
}
}

ActionScript - Get Instance Name From Constructor Without Passing Parameters?

is it possible to obtain the instance name of a class from the class without having to manually pass the instance name as a string parameter to the class constructor?
//Create New SizeClass
var big:SizeClass = new SizeClass();
//-------------
package
{
public class SizeClass
{
public function SizeClass()
{
trace( //-- Instance Name "big" --// );
}
}
}
No, it is not possible to know anything about the containing code block during a constructor, save what you can learn from the stack trace (though that's not available except in the debugger version of Flash). Even if you had a global access point for the containing class, it still would not allow for that access.
Think of a constructor like a method call. In a line of AS, it will be called before the assignment. Eg: var a:Foo = new Foo() the Foo is created (the constructor completes), and then a is populated with whatever just happened. After that point a will remain agnostic of its context (because of encapsulation) unless it is told about it (this is even true on a DisplayObject -- try this( var mc:MovieClip = new MovieClip(); trace( mc.root ) //this will be null ).
I'm keeping this because it is useful albeit not useful to your original answer.
You can always get the name of a class with getQualifiedClassName from the flash.utils package. You can't get a DisplayObject's until well after it has been constructed, but you can simulate this by (I believe) overriding function set name( value:String ):void. If that doesn't work, then try finding it after Event.ADDED and/or Event.ADDED_TO_SAGE.
The instance name isn't very important. You'd better store references of the instances inside an array.
var sizes:Array = new Array();
var big:SizeClass = new SizeClass();
sizes.push( big );
When you want to access them, you can loop through the array.
for (var i:uint = 0; i < list.length; ++i)
{
var size:SizeClass = list[i] as SizeClass;
trace( size );
}
BTW: Instead of an instance name it is possible to add an automatic index to your class.
package
{
public class SizeClass
{
private static var global_index:int = 0;
public const INDEX:int = global_index ++;
}
}
Which you can access like this:
var big:SizeClass = new SizeClass();
trace(big.INDEX) // 0
var small:SizeClass = new SizeClass();
trace(small.INDEX)// 1
source: http://blog.stroep.nl/2010/08/auto-increment-as3-class/

Actionscript 3: Array Scope in a Document Class

I have the following function to set up cards in a game. I created one array to hold the kind of cards, and another array to hold the position of the cards.
private function setPlayerCard(cardNumber:int, cardPos:int):void{
for (var i:int = 1; i < _CardGridInstance.numChildren+1; i++) {
var _position:MovieClip = MovieClip(_CardGridInstance.getChildByName("Position_" + i));
cardPositions[i] = _position;
cardPositions[i].pos_name.text = "position" + i;
cardPositions[i].id = ["pos"+i];
}
for (var j:int = 1; j < numCards+1; j++) {
var _c:Class = getDefinitionByName("Card_" + j) as Class;
var _cardInstance:MovieClip = new _c();
cards[j] = _cardInstance;
}
cards[cardNumber].x = _CardGridInstance.x + cardPositions[cardPos].x - 1;
cards[cardNumber].y = _CardGridInstance.y + cardPositions[cardPos].y;
addChild(cards[cardNumber]);
}
So if I want to set the card number "3" in position "5" I just write:
setPlayerCard(3,5);
The problem I can see is that every time I'd like to place a card, I am creating two arrays every time. I would like to make the arrays "global" (i.e. create it in my constructor in my document class) and reuse it in the function "setPlayerCard" however I am getting errors when I try to do so.
Any suggestions?
This is a perfect case for a Singleton static class data model. You can get the instance of the Singleton from throughout the application as it is a static class, and it can contain the two arrays without duplication.
pixelbreaker has a nice basic Singleton AS3 example that you can build from.
It's a little difficult to answer accurately without knowing how you are creating the variables and what errors you're getting. Can you post the entire class and the errors?
I can, however, recommend that you do not use the Singleton pattern. This is not a perfect case for a Singleton. The Singleton pattern has no place in OOP, it's procedural programming wrapped up like OO, but that's an argument for elsewhere.
This is, though, a perfect case for a class level variables. The following is a simple example. There are a few missing variable declarations though (numCards), as I don't know where you're creating and setting them.
package{
import flash.display.Sprite;
public class CardGame extends Sprite{
private var cardPositions:Array = new Array();
private var cards:Array = new Array();
public function CardGame(){
for var i:uint = 1; i <= _CardGridInstance.numChildren; i++) {
var position:MovieClip = MovieClip(_CardGridInstance.getChildByName("Position_" + i));
cardPositions[i] = position;
cardPositions[i].pos_name.text = "position" + i;
cardPositions[i].id = ["pos"+i];
}
for(i = 1; i <= numCards; i++) {
var c:Class = getDefinitionByName("Card_" + i) as Class;
var cardInstance:MovieClip = new c();
cards[i] = cardInstance;
}
}
private function setPlayerCard(cardNumber:uint, cardPos:uint):void{
cards[cardNumber].x = _CardGridInstance.x + cardPositions[cardPos].x - 1;
cards[cardNumber].y = _CardGridInstance.y + cardPositions[cardPos].y;
addChild(cards[cardNumber]);
}
}
}
This way you only create and populate the arrays once and you can access them from anywhere within the CardGame Class. They are not global but they are within the scope of the setPlayerCard method.
You may get errors as objects might not be instantiated when the Document Class' constructor gets called, but that can be worked around.
What is the need for the variable to be public and static?
Static means that the variable is on the Class, not instances of the Class. So every "CardGame" instance will share the same static variable. I presume, because this is the Document Class, that you will not have more than one instance of it. So there is no reason for that.
The only other reason, because you declared it public, is to make the variable accessible from outside the Class through CardGame.cardPositions. This is bad practice as you shouldn't allow other objects to directly manipulate a Classes internal data. That breaks encapsulation. Since this is the Document Class and the top of the hierarchy, you should pass a copy of the data to whichever object needs it and wait for an event to retrieve the updated data. That way you can sanitise the data before using it and you're not just blindly trusting other objects to respect your data.
http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
I tried using the Singleton class, but since I had to reference MovieClips that were already on the display list, I opted for a different solution from "Actionscript 3 Tip of the Day":
http://www.kirupa.com/forum/showthread.php?p=2110830#post2110830
package {
public class ClassName {
public static var myArray_1:Object = new Object;
public static var myArray_2:Object = new Object;
public function ClassName() {
//constructor
Whatever();
DoStuffWithWhatever();
}
private function Whatever() {
// put stuff into the array here
}
private function DoStuffWithWhatever():void {
// do stuff with the array values here.
}
}
}