How to access Movieclips individually in a for loop as3 - arrays

Lets say that mySaveNewT.data.myNText = 20, and in a for loop, 20 MovieClips (tbox) are populated on the stage. When a tbox instance gets clicked I want to change its visibility to false.
How do I reference an individual MovieClip that gets clicked, without having to set every MovieClip's visibility to false? (i.e if MC[2] and MC[10] get clicked, but the rest aren't)
How do I push this into an Array?
Here is my for loop:
for (var i: Number = 0; i < mySaveNewT.data.myNText; ++i) {
newText = new tbox();
newText.x = -220;
newText.y = -513 + i * 69 + 0 * 3.8;
VWD.addChild(newText);
}

To push into an array, and add the click listener and change visibility, see code comments:
//you need to define an array to store the clips in
var clickedBoxes:Array = []; //this makes a new empty array, same as doing: = new Array();
for (var i: Number = 0; i < mySaveNewT.data.myNText; ++i) {
newText = new tbox();
newText.x = -220;
newText.y = -513 + i * 69 + 0 * 3.8;
VWD.addChild(newText);
newText.addEventListener(MouseEvent.CLICK, clipClickHandler,false,0,true); //now you add a click listener to this clip
}
function clipClickHandler(e:MouseEvent):void {
//e.currentTarget will be a reference to the item that was clicked
MovieClip(e.currentTarget).visible= false; //we wrap e.currentTarget in MovieClip so the compiler knows it has a visible property (casting)
clickedBoxes.push(e.currentTarget);
}
To loop through your array later:
for(var index:int=0;index<clickedBoxes.length;index++){
clickedBoxes[index].visible = true; //you may have to cast to avoid a compiler error MovieClip(clickedBoxes[index]).visivle = true;
}

Related

How to take instance name which numbering by array and the number can be operated?

The intention of the following ActionScript script is to allow a player to move by clicking a button, wherein myarray represents places they are allowed to move to.
I'm having trouble making my click event handler work properly. For example, how can I extract the (x, y) coordinates of the click from the MouseEvent event in order to perform further processing?
a.addEventListener(MouseEvent.CLICK, bergerak);
b.addEventListener(MouseEvent.CLICK, bergerak);
c.addEventListener(MouseEvent.CLICK, bergerak);
d.addEventListener(MouseEvent.CLICK, bergerak);
function bergerak (Event:MouseEvent) {
var namatombol:String = Event.currentTarget.name;
var myarray:Array = [];
for (var i:int = 0; i < 3; i++) {
myarray[i] = this["kotak" + i];
if (namatombol == "a") {
MovieClip(root).pemain.x = MovieClip(root).myarray[i].x;
MovieClip(root).pemain.y = MovieClip(root).myarray[i].y;
}
}
}
I understood that you're willing to move a player display object (like a MovieClip) to the clicked button position on stage. In this case, your function will be as follows:
function bergerak(event:MouseEvent):void
{
MovieClip(root).pemain.x = event.target.x;
MovieClip(root).pemain.y = event.target.y;
}

How to add Movie Clips to Array?

Hey everyone so I have been at this for awhile now and I'm trying to figure out the best way to go about this. So I have an array of Movie Clip Objects calledouterPlanets and they are added to an array called aPlanetArray so these planets in the array are added to the stage and have spacing between them all. When the Player touches the screen the character jumps on another planet and the planets scroll down on the +y axis to keep the character positioned to the center.
I add 10 planets to the stage because for performance Issues I don't want to add a lot and lose FPS so my idea was when the array is getting low such as the planet array is <= 5 then add more planets to the top position of the last last planet. Hope I am making sense. Think of it like a stack of blocks the blocks fall down one by one and more is added to the top of them as more fall down so its never ending.
Here is how I add them to the stage:
//Instantiate Arrays
aPlanetArray = new Array();
//Numbers
xSpacing = 100;
ySpacing = 200;
startPoint = new Point((stage.stageWidth / 2), (stage.stageHeight / 2) );
addOuterPlanets();
private function addOuterPlanets():void
{
for (var i:int = 0; i < nPlanets; i++)
{
outerPlanets = new mcOuterPlanets();
outerPlanets.x = startPoint.x + (xSpacing * i);
outerPlanets.y = startPoint.y - (ySpacing * i);
stage.addChild(outerPlanets);
aPlanetArray.push(outerPlanets);
}
}
The only thing I can come up with at the moment is this:
if (aPlanetArray.length <= 5)
{
addOuterPlanets();
}
This adds a new set of planets but of course just adds them to the center of the stage and not on top of the other planets. Any idea how to accomplish this?
Current Progress:
private function collisionPlanetHandler():void
{
for (var i:int = 0; i < aPlanetArray.length; i++)
{
var currentPlanet:mcOuterPlanets = aPlanetArray[i];
planetContainer.addChild(aPlanetArray[i]);
if (character.hitTestObject(currentPlanet) && !nextlevel)
{
trace("HIT");
yDown = (stage.stageHeight / 2) - (currentPlanet.y - 200); //have object tween to center of stage or where was last positioned
//tap back to false
tap = false;
nextlevel = true;
if (!bNullObject) // have null object so doesnt loop again and cause error for planet == null
{
planet.destroy();
planet = null;
}
bNullObject = true;
planetHit = currentPlanet; // to land on correct planet
aPlanetArray.splice(i, 1);
randomRotation = randomNumber(1, 2); //Stop in random rotation for next planet
TweenLite.to(planetContainer, 2.0, { y:yDown, ease:Elastic.easeOut } );
planetIncrement -= 300;
addPlanet(randomNumber((stage.stageWidth/2) - 220, ((stage.stageWidth/2)) + 220), planetIncrement);
}
}
}
example code
function gameSetup():void{
setupUsers();
loadSounds();
createLevel(_level1);
addInitialPlanets();
addCharacter();
}
private function addInitialPlanets():void{
for (var i:int = 0; i < nPlanets; i++){
addPlanet(startPoint.x + xSpacing * i, startPoint.y + ySpacing * i);
}
}
private function addPlanet(xPos:Number, yPos:Number):void{
p = new mcOuterPlanets();
// var p:mcOuterPlanets = new mcOuterPlanets(); // this is preferred method
p.x = xPos;
p.y = yPos;
stage.addChild(p);
// addChild(p); // this is preferred method
aPlanetArray.push(p);
}
Now when you need to add another planet above the others do
addPlanet(xPos, yPos);
// where xPos is desired X and yPos is desired y
You see what is happening here? I'm positioning the planet by using a separate function. You can offload other tasks related to add a planet as well. Imagine something like this:
addPlanet(xPos, yPos, color, size, speed, ringCount);
Get the idea?
Also you'll want to remove the planets that are far below the player to prevent slowdown. Or you could simply move the ones far below up to the top to recycle them instead of creating new planets all the time.
Draft example...
#Nathan , Neal Davis is right as usual, but I'd push the Vector, then addChild at its current index... Avoid the Arrays if You can. (if the instances are made by the same Class).
var aPlanetArray:<Vector>.MovieClip = new <Vector>.MovieClip(10);
// or new <Vector>.MovieClip(); if You don't want to restrict the amount of items in the Vector.
// or new <Vector>.McOuterPlanets() if McOuterPlanets is a Class.
private function addOuterPlanets():void {
for (var i:int = 0; i < nPlanets; i++){
aPlanetArray.push(new mcOuterPlanets());
aPlanetArray[i].x = startPoint.x + (xSpacing * i);
aPlanetArray[i].y = startPoint.y - (ySpacing * i);
addChild(aPlanetArray[i]);
};
[EDIT]
If you choose to make a Vector of MovieClip (var aPlanetArray:<Vector>.MovieClip = new <Vector>.MovieClip(10)),
You must use aPlanetArray[i] as McOuterPlanets to get the methods of
Your McOuterPlanets methods!
So, in the case of a Vector of MovieClip (aPlanetArray == .MovieClip), if You want to use the methods of McOuterPlanets methods You have to do :
var outerP : McOuterPlanets = aPlanetArray[someIndex] as McOuterPlanets;.
Then You may call outerP.someMethodOfMcOuterPlanets();
Just because McOuterPlanets extends the MovieClip Class.
Never use Vectors if You have to add different types of datas in Your Vector, use the Array Class instead.
This will works but this is tricky an total nonsense!
Example :
var vectorOfStrings:Vector.<String> = Vector.<String>([["a","b","c"],["d","e","f"]]);
// this works and Your Vector contains only Strings so OK.
trace("");
trace("length of the Vector = " + vectorOfStrings.length);
trace("vectorOfStrings.toString() = " + vectorOfStrings.toString());
trace("vectorOfStrings[0] = " + vectorOfStrings[0]);
trace("vectorOfStrings[1] = " + vectorOfStrings[1]);
var vectorOfArrays:Vector.<Array> = Vector.<Array>([["a","b","c"],[1,2,3]]);
// this works but this is tricky an total nonsense
// use the Array Class instead!
trace("\n NEVER DO THIS! Use the Array Class instead!");
trace(" NONSENSE!");
trace("length of the Vector = " + vectorOfArrays.length);
trace("vectorOfArrays.toString() = " + vectorOfArrays.toString());
trace("vectorOfArrays[0] = " + vectorOfArrays[0]);
trace("vectorOfArrays[1] = " + vectorOfArrays[1]);
[/EDIT]
I hope this may help.
Check to the reference for :
ActionScript 3 fundamentals: Arrays
ActionScript 3 fundamentals: Associative arrays, maps, and dictionaries
ActionScript 3 fundamentals: Vectors and ByteArrays

creating an array for a snapping function with ActionScript 3

I created a puzzle where you can drag and drop 16 pieces. I used an array so that the code doesn't get too big. Now I want to add an function where each puzzle piece snaps into right place once you get near the destination.
My problem is that I don't know how to create an array which can achieve my goal. I tried the following(without an array but that creates too much code if I do it with all 16 puzzle pieces):
if(target1_mc.hitTestObject(piece1_mc.tar1_mc))
{
piece1_mc.x = 207,15;
piece1_mc.y = 119,25;
}
Code:
import flash.events.Event;
import flash.events.MouseEvent;
var puzzleArr:Array = new Array (piece1_mc, piece2_mc, piece3_mc, piece4_mc,
piece5_mc, piece6_mc, piece7_mc, piece8_mc,
piece9_mc, piece10_mc,
piece11_mc, piece12_mc, piece13_mc, piece14_mc, piece15_mc, piece16_mc);
for (var i:uint =0; i < puzzleArr.length; i++) {
puzzleArr[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
puzzleArr[i].addEventListener(MouseEvent.MOUSE_UP, drop);
}
function drag(event:MouseEvent):void {
event.currentTarget.startDrag();
}
function drop(event:MouseEvent):void {
event.currentTarget.stopDrag();
}
There a few ways to accomplish this. The easiest, is to add a dynamic property to your pieces that stores the target (correct location object) for the piece.
var puzzleArr:Array = []; //you don't really even need the array in my example
var tmpPiece:MovieClip; //this stores the current dragging piece, and I also reuse it in the loop below
//I don't like typing a lot, so let's use a loop for all 16 pieces and their targets
for(var i:int=1;i<=16;i++){
tmpPiece = this["piece" + i + "_mc"]; //get a reference to piece whose number matches i
if(!tmpPiece){
trace("Sorry - there is no piece called: 'piece" + i + "_mc'");
continue;
}
//give the piece a dynamic property that is a reference to it's target spot
tmpPiece.targetTile = this["target" + i + "_mc"];
if(!tmpPiece.targetTile){
trace("Sorry - there is no target called: 'target" + i + "_mc'");
continue;
}
tmpPiece.tar_mc = tmpPiece["tar" + i + "_mc"]; //it would be better to just take the number out of each pieces tar_mc child object making this line uneccessary
//track where the piece is placed
tmpPiece.startingPos = new Point(tmpPiece.x, tmpPiece.y);
//only add the mouse down listener to the piece (not mouse up)
tmpPiece.addEventListener(MouseEvent.MOUSE_DOWN, drag);
//if still using the array, add the piece to the array
puzzleArr.push(tmpPiece);
}
Next, add a mouse move listener only while dragging
function drag(event:MouseEvent):void {
tmpPiece = event.currentTarget as MovieClip; //assign the dragging object to the tmpPiece var
tmpPiece.startDrag();
//add a mouse move listener so you can check if snapping is needed
tmpPiece.addEventListener(MouseEvent.MOUSE_MOVE, moving);
//add the mouse up listener to the stage - this is good because if you drag fast, the mouse can leave the object your dragging, and if you release the mouse then it won't trigger a mouse up on the dragging object
stage.addEventListener(MouseEvent.MOUSE_UP, drop);
}
function drop(event:MouseEvent):void {
//stop all dragging
this.stopDrag();
if(tmpPiece){
//remove the mouse move listener
tmpPiece.removeEventListener(MouseEvent.MOUSE_MOVE, moving);
//ensure a snap at the end of the drag
if(!checkSnapping()){
//if not snapped, reset it's position
tmpPiece.x = tmpPiece.startingPos.x;
tmpPiece.y = tmpPiece.startingPos.y;
}
}
//remove the mouse up listener
stage.removeEventListener(MouseEvent.MOUSE_UP, drop);
}
Now lets do the snapping in the mouse move handler:
function moving(e:MouseEvent = null):void {
checkSnapping();
}
//return true if snapped
function checkSnapping():Boolean {
if(tmpPiece && tmpPiece.tar_mc.hitTestObject(tmpPiece.targetTile)){
tmpPiece.x = tmpPiece.targetObj.x - tmpPiece.tar_mc.x;
tmpPiece.y = tmpPiece.targetObj.y - tmpPiece.tar_mc.y;
return true;
}
return false;
}
for (var i:int = 0; i < puzzleArray.length; i++)
{
if(puzzleArray[i].hitTestObject(puzzleArray[i]._target))
{
puzzleArray[i].x = puzzleArray[i]._xGoal;
puzzleArray[i].y = puzzleArray[i]._yGoal;
}
}
Obviously you'll need to add a couple of properties to the puzzle piece objects (_xGoal, _yGoal,_target) and you can do that however you'd like. You could probably use a loop, but only if there is some sort of order to them. If they are not of equal size and in a grid, then you'll have to obviously just manually type these in.
If they are in a grid and each piece is equal size, let me know if you need help with creating those properties in a loop.

How to re add elements in array to their same position on stage?

Hey everyone so in my game I am creating I add all my interactive objects to the stage by simply dragging from the library and placing them on the stage. Then in Flash Develop in my Engine Class I place them inside an array like so:
private var aZebraArray:Array;
In my constructor I add the elements on the stage through their instance names I gave them Like so:
aZebraArray = [startScreen.zebra_Front, startScreen.zebra_Middle, startScreen.zebra_Back, startScreen.zebra_Far];
Then in my Enter_Frame Listener I loop through the objects on stage like so for the Hit Test:
private function Round_1Controls():void
{
trace(aZebraArray.length);
for (var i:int = 0; i < aZebraArray.length; i++)
{
var currentZebra = aZebraArray[i];
if (crosshair.bullet.hitTestObject(currentZebra) && shotGun)
{
trace("HIT");
aZebraArray.splice(i, 1);
currentZebra.gotoAndPlay("DIE");
shotGun = false;
//Add points
nPoints += 50;
updatePointsText();
//Animals hit for stars
animalsHit ++;
}
}
Now in my game if the player doesn't get 3 stars he is able to Retry and restart that round over. The PROBLEM That I have run into is that I don't quite know how I would go about having the objects that are on stage placed back where they first started from because when the round starts the "Zebras" run across the stage through a custom tween I made in each of them. Also I believe I could just create a new array like so:
aZebraArray = new Array();
aZebraArray = [startScreen.zebra_Front, startScreen.zebra_Middle, startScreen.zebra_Back, startScreen.zebra_Far];
but then how could i restart all their animations so they can run across the stage again? I know I can just create their own class and add them in array then control them through a timer object but I add them manually on stage because their are a lot of bushes that they need to hide behind or be in front of and to code that would be exhausting. If anyone can help I would Appreciate it thanks!
Here is what I have in my retry Function but it is only adding 1 or 2 of the objects in the array back to the stage.
private function replayRound_1(e:MouseEvent):void
{
continueScreen.mcRetry.removeEventListener(MouseEvent.CLICK, replayRound_1);
continueScreen.destroyContinueScreen();
round1 = true;
nAmmo = 0;
nAmmo += 5;
updateAmmoText();
animalsHit = 0;
hasAmmo = true;
gameChannel = gameSound.play(0, 999);
//aZebraArray = [];
aZebraArray = new Array();
aZebraArray = [startScreen.zebra_Front, startScreen.zebra_Middle, startScreen.zebra_Back, startScreen.zebra_Far];
for (var i:int = 0; i < aZebraArray.length; i++)
{
var currentZebra = aZebraArray[i];
currentZebra.gotoAndStop("RUN");
}
}

How to remove object from index in array AS3

Hey Everyone so I've been killing myself over this and this is probably the last thing I need help on to finally finish this project.
So I have a timer event that puts the Movie clip in the array onto the Stage. The MovieClip is named mSquare and from the timer event I add it like so:
private function addSquare(e:TimerEvent):void
{
mSquare = new mcSquare();
stage.addChild(mSquare);
mSquare.x = (stage.stageWidth / 2);
mSquare.y = (stage.stageHeight / 2) + 450;
aSquareArray.push(mSquare);
trace(aSquareArray.length);
}
Now what I am trying to Accomplish is when the user clicks or has its mouse down on the object, I want that object that the user clicked to be removed from the stage.
Now I can't get it to function properly when the user clicks on one of the MovieClips from the array thats added to the stage. Or if I do then MovieClip that was currently clicked doesnt get destroyed but rather another instance of it on the stage gets destroyed. Its just real bad.
So Here is how I have it set up so far...
In my Constructor:
stage.addEventListener(MouseEvent.MOUSE_DOWN, movieClipHandler);
Then the movieClipHandler MouseEvent:
private function movieClipHandler(e:MouseEvent):void //test
{
mSquare.addEventListener(MouseEvent.MOUSE_DOWN, squareIsBeingClicked);
}
Then in the squareIsBeingClicked Function:
private function squareIsBeingClicked(e:MouseEvent):void
{
var square:DisplayObject = e.target as DisplayObject; // clicked square
var i:int = aSquareArray.indexOf(square); // index in the array
if (i < 0) //THIS IS WHERE I GET CONFUSED
{
// the MC is out of the array
trace("Clicked");
mouseIsDown = true;
checkSquareIsClicked();
} else
{
// the MC is in the array
}
}
And finally i have a function called checkSquareIsClicked to do all the work:
private function checkPopIsBeingClicked():void
{
//Loop through all pops
for (var i:int = 0; i < aPopArray.length; i++)
{
//Get current pops in i loop
var currentpop:mcPop = aPopArray[i];
if (mouseIsDown)
{
trace("Current Pop Destroyed")
aPopArray.splice(i, 1);
currentpop.destroyPop();
nScore ++;
updateHighScore();
updateCurrentScore();
mouseIsDown = false;
//Add Explosion Effect
popExplode = new mcPopExplode();
stage.addChild(popExplode);
popExplode.y = currentpop.y;
popExplode.x = currentpop.x;
}
}
}
I know I am doing something really wrong because it shouldnt take this much functions to initiate this array of mouse event. Also someone on here helped me out with the display object and idex as shown above but not sure how to truly implement it. I've exhausted all ideas. Any Help would be appreciated or any pointers. Thank you!
As #Rajneesh answer indicates, adding your mouse event listener to your MovieClip instead of using the stage mouse event to add the listener, is the correct way to go. That means instead of doing this...:
stage.addEventListener(MouseEvent.MOUSE_DOWN, movieClipHandler);
private function movieClipHandler(e:MouseEvent):void {
mSquare.addEventListener(MouseEvent.MOUSE_DOWN, squareIsBeingClicked);
}
Would be replaced in your addSquare function:
private function addSquare(e:TimerEvent):void {
mSquare = new mcSquare();
stage.addChild(mSquare);
mSquare.x = (stage.stageWidth / 2);
mSquare.y = (stage.stageHeight / 2) + 450;
aSquareArray.push(mSquare);
//look here
mSquare.addEventListener(MouseEvent.MOUSE_DOWN, squareIsBeingClicked);
trace(aSquareArray.length);
}
Now you can change your removal functions. I'm going to alter some of this code to help you optimize it and still achieve the desired effect. Let's start with squareIsBeingClicked:
private function squareIsBeingClicked(e:MouseEvent):void {
var square:DisplayObject = e.target as DisplayObject; // clicked square
var i:int = aSquareArray.indexOf(square); // index in the array
//this is where you will no longer be confused :)
if (i != -1) {
trace("Clicked");
mouseIsDown = false;
onSquareIsClicked( square ); //this is in place of your checkSquareIsClicked
square.parent.removeChild( square );
aSquareArray.splice( i, 1 ); //remove element from the array
//remove the listener, very important
square.removeEventListener( MouseEvent.CLICK, squareIsBeingClicked );
square = null; //null it if we are not using it again, ready to be garbage collected
}
}
You now no longer need all the removal pieces in your previous checkSquareIsClicked. As you probably noticed I added a function onSquareIsClicked(), this is to help with any functionality you might need to do when this event is happening. Since you are adding an "explosion" where the object was selected, here's what onSquareIsClicked() looks like:
private function onSquareIsClicked( square:DisplayObject ):void {
popExplode = new mcPopExplode();
stage.addChild(popExplode);
popExplode.y = currentpop.y;
popExplode.x = currentpop.x;
//square.destroyPop(); //obviously this function will not work on a type displayObject
//in which case you just need to cast square to the object containing the method
nScore ++;
updateHighScore();
updateCurrentScore();
}
Add mouse click events to objects to be removed and get target and remove it like so:
(Note: Also, no need to add those MovieClips to array ( add only if necessary))
private function addSquare(e:TimerEvent):void
{
mSquare = new mcSquare();
mSquare.addEventListener(MouseEvent.CLICK, removeSquare);
stage.addChild(mSquare);
//Position here mSquare
}
private function removeSquare(e:MouseEvent):void
{
var tempObject:MovieClip = MovieClip(e.currentTarget); //get the square object
removeChild(tempObject);
tempObject = null;
}

Resources