Actionscript 3 - Converting strings to command - actionscript-3

I have four Movieclips inside four movieclip containers, and a filter called "myShadowFilter", like so:
option1BlueBox
is a movieclip inside
option1Container
and
option2Container
is a movieclip inside
option2BlueBox
and so on. I want to do this:
option1Container.option1BlueBox.filters = [myShadowFilter]; //line1
option2Container.option3BlueBox.filters = [myShadowFilter]; //line2
option3Container.option4BlueBox.filters = [myShadowFilter]; //line3
option4Container.option5BlueBox.filters = [myShadowFilter]; //line4
except with a loop, becuase I'm probably going to add more containers, each with a movie clip inside. A sudo-code of what I want to do is:
var containers:int = 1;
for (var i:int = 1; i<containers + 1, i++) {
'option' + i + 'Container.option' + i + 'BlueBox.filters = [myShadowFilter];';
}
Basically, I just want one loop which will run all the 4 commands. How do I make it work? It is giving me errors (as I expected) saying that there are syntax errors and colons are expected.

Use the Array access operator. For more details, see this.
var containers:int = 1;
for (var i:int = 1; i<containers + 1, i++) {
this['option' + i + 'Container']['option' + i + 'BlueBox'].filters = [myShadowFilter];
}
You could probably simplify this further by giving the blue box clip the same instance name (it only needs to be unique within the current scope). Then you could do something like this:
// Create an array of containers
var containers = [
option1Container,
option2Container,
option3Container,
option4Container
];
// Loop through each container and apply the filter
// to the blue box container clip
for (var i = 0; i < containers.length; i ++)
{
containers[i].option1BlueBox.filters = [myShadowFilter];
}

Related

problem accessing dynamic movieclips by name in adobe animate

I've done this a million time, but here it didn't work.
I have a game_mc inside a animate.fla. inside this clip I generate a view targetareas to place stones on it. ok, the TargetArea is a simple Movieclip inside my lib.
I can see everything, I can click on the area an get the propper name, I can get the names of the clips inside game_mc.
but I can't access it by using game_mc[clipname]
for (var i:int = 1; i<= 20; i++){
var targetArea:TargetArea = new TargetArea();
targetArea.txt.text = String(i);
var modu = ((i-1) %5);
targetArea.x = 100 + modu * 340;
var abs = int((i-1) / 5);
targetArea.name = "targetarea_" + String(i)+ "_mc";
targetArea.mouseChildren = false;
targetArea.y = 100 + (abs * 200) ;
game_mc.addChild(targetArea);
}
for(var x:int=0;x < game_mc.numChildren;x++) {
trace (game_mc.getChildAt(x).name);
}
for (var i:int = 1; i< 20; i++){
var targetName:String = "targetarea_" + i + "_mc"
trace( game_mc[targetName].x);
}
I think the name you assign your TargetArea instances isn't automatically converted
into a property of the DisplayObject you attach it to. As far as I remember though this
nonchalant way of accessing MovieClips using array access used to work prior to AS3.
The more elegant solution is to retrieve the child using getChildByName().
trace(game_mc.getChildByName(targetName).x);
Additionally, in case game_mc is an instance of MovieClip or a dynamic class you can make the TargetArea instances a property of it using:
game_mc[targetArea.name] = targetArea;
This way you can access them using game_mc[name].property afterwards.

AS3 Add Child at the position of another Child

Hey I have got some cavemen that when they build huts I want the huts to be added at the coords of the caveman I last clicked on which requires the ability to know exactly what caveman the user clicked on/tapped. Here is the code for spawning in the cavemen:
//////////////////////
///Starting Cavemen///
//////////////////////
var cavemanVar:Array = new Array(50);
for (var i:Number = 0; i < 50; i++)
{
cavemanVar[i] = 0;
}
var foo:MovieClip = new btn_caveman();
cavemanVar[0] = addChildAt(foo, 7);
var bar:MovieClip = new btn_caveman();
cavemanVar[1] = addChildAt(bar, 7);
cavemanVar[0].x = 335.50;
cavemanVar[0].y = 316.55;
cavemanVar[1].x = 335.50;
cavemanVar[1].y = 369.5;
stage.addEventListener(Event.ENTER_FRAME, example2);
function example2 (evt:Event) {
for (i = 0; i < 50; i++)
{
if (cavemanVar[i] != 0)
{
cavemanVar[i].addEventListener(TouchEvent.TOUCH_TAP, btn_cavemanMenu3);
}
}
}
function option1CavemenSpawn():void {
trace("using option 1")
actions += 1;
score += 5;
remaningActions += 1;
updateTextBox();
var foo6:MovieClip = new btn_caveman();
cavemanVar[2] = addChildAt(foo6, 7);
cavemanVar[2].x = 352.10;
cavemanVar[2].y = 260.80 + Math.random() * (392.40 - 260.80);
}
Any help would be great, I have tried using 'cavemanVar', 'cavemanVar[2]', 'cavemanVar[i]' and nothing is what I want it to be.
Hope I explained it properly it's a tricky thing to explain. I also have a move caveman feature I want to implement which would select the last clicked/tapped caveman and move it where the user clicks/taps so can any of this be done and if so how?
EDIT:
function btn_cavemanMenu3(event:TouchEvent):void {
btn_cavemanM.gotoAndStop(2);
trace('2');
allowBuildHut();
cancelTapCaveman();
allowTapCavemanClose();
if (remaningActions <= 2 || stone <= 29) {
cancelBuildHut();
}
}
Do you mean something like,
cavemanVar[i].addEventListener(TouchEvent.TOUCH_TAP, onTap);
function onTap(e:TouchEvent):void {
var caveman:btn_caveman = e.currentTarget as btn_caveman;
trace("caveman tapped --- (" + caveman.x + ", " + caveman.y + ")");
}
Okay, some things I noticed right away:
Attaching eventListeners with each frame, again and again. This will make your game slow if you make your game bigger. I'm not sure, but I think multiple event listeners with the same arguments don't stack, so it's not THAT bad.
Missing a return type for example2.
But aside from that, I think the reason that what you're trying to do doesn't work is because you're not referencing the selected caveman in your btn_cavemanMenu3 function. Via event.currentTarget you can reference the tapped caveman.
Currently, your question name and your question description conflict. What exactly do you wish to achieve? What is working and what isn't working right now?

Trying to remove object throws error 1009 cannot access a property or method of null object reference

Working on a flash game, in a previous game I had enemies come in by using an array and when they were killed or moved off the stage I would just remove them from the array. For some reason when I use exactly the same code in this game, it throws a 1009: error when I try to remove the array object, basically saying that there's nothing there. . . Which is strange.
Here's the code:
public function addZombie()
{
var zom:Zombie = new Zombie();
zom.y = 20;
zom.x = Math.floor(Math.random()*(1 + 500 - 30)) + 30;
addChild(zom);
zombies.push(zom);
numZombies++;
}
That's the function where it's added in, zombies is the array and it's pushed into the array in this function. Here's the code where I'm attempting to remove it:
for (var i:int = 0; i < zombies.length; i++)
{
if (zombies[i].y + zombies[i].height / 2 > 400) {
removeChild(zombies[i]);
zombies.splice(i,1);
numZombies--;
addZombie();
}
}
removeChild(zombies[i]); <-- This is the part that throws the error when it attempts to remove it. It removes some of them strangely enough, but not all of them.
I don't believe the loop is doing quite what you expect it to. When you remove an element from an array in this way, all the elements after the removed elements are moved down. So, if you have code like:
var testArr:Array = new Array();
testArr.push('First');
testArr.push('Second');
testArr.push('Third');
testArr.push('Fourth');
for (var i:int = 0; i < testArr.length; i++) {
testArr.splice(i,1);
}
The results of the loop will be:
i=0, testArr = ['Second', 'Third', 'Fourth']
i=1, testArr = ['Second', 'Fourth']
i=2 END OF LOOP
It would probably be better to use a while loop, incrementing the index only if the element is not removed (since removing the element moves a new element to that index position).
I don't see why you're getting the null object reference, but this would be causing other problems (why some are removed but not all).
The explanations of Bill Turner are the correct ones, but as it didn't seem to help you fix your issue, you might want to try this:
var zombieCount:int = zombies.length;
for (var i:int = 0; i < zombies.length; i++)
{
var zombie = zombies[i];
if (zombie.y + (zombie.height / 2) > 400) {
removeChild(zombie);
zombies.splice(i,1);
i--; // So that the loop will pass with the same value next time
numZombies--;
}
}
for (var j:int = zombies.length; j < zombieCount; j++)
{
addZombie();
}

actionscript for loop iterator to change movie clip name

I have a bunch of movie clips I created in flash CS5 and are all placed within the stage. I control each one of them dynamically with code using ActionScript 3. However I want to control all of them at the same time using a for loop and just change the width of each element but its not working.
Here is my code:
for(var i:Number = 0; i < 100; i++)
{
leftBar+i.width = ( Math.round(channel.rightPeak * 1.1) ) + 60;
}
So I have 100 bars each called leftBar and their number. So the firstBar is leftBar1, then leftBar2 and so on. I cant get it to work however. I have tried "leftBar"+i and also leftBari but none of them seem to work.
The correct way to select each of those MovieClips in your loop is:
this["leftBar" + i]
New code:
// Note: We've changed the initial value of i to 1 because you mentioned that
// your first MovieClip was called 'leftBar1' rather than 'leftBar0'.
for(var i:int = 1; i <= 100; i++)
{
var current:MovieClip = this["leftBar" + i];
current.width = Math.round(channel.rightPeak * 1.1) + 60;
}
Basically you want to select the property leftBar0, leftBar1, etc from this using square brackets. It is the same as doing this:
this.leftBar0
And can also be used for any properties or methods of any other class:
// Example of Square Bracket notation.
var sprite:Sprite = new Sprite();
sprite["x"] = 10;
trace(sprite.x);
this["addChild"](sprite);

Flex AdvancedDataGrid c/p rows issue

I'm a newbie in Flex/AS3 development and I came across an issue that bugs me for a while now. I'm using an AdvancedDataGrid with some columns, and an ArrayCollection as the provider. I would like to make a copy/paste functionality so that multiple rows can be selected, copied, and then pasted below the selected (or last selected row).
The problem is when I copy the data from one row to another, both of those rows become highlighted on mouse-over (upper instance isn't even selectable) - just as in this topic: Flex DataGrid/DataProvider bug?
First I thought it was the issue of copying the reference, but it persist even if I use ObjectUtil.copy() method. Furthermore, I manually change one of the properties called "order" so that the objects of the ArrayCollection aren't identical, but it doesn't help. Dataprovider is called newTreatmentData, and the DataGrid is newTreatmentDG.
Any suggestions are more then welcome.
Here's part of the code that is relevant:
private function getSelectedRow(event:Event):void
{
selectedRow = newTreatmentDG.selectedIndex;
}
private function copySelection(event:Event):void
{
bufferData = new ArrayCollection();
var sortedIndices:Array = newTreatmentDG.selectedIndices.sort();
for (var i:int = 0; i < newTreatmentDG.selectedIndices.length; i++){ //copy selected rows to the buffer
var j:int = sortedIndices[i];
bufferData.addItem(newTreatmentData[j]);
}
}
private function pasteSelection(event:Event):void
{
var rowsToMove:int = newTreatmentData.length - selectedRow - 1; //number of rows to move after pasting
for (var i:int = 1; i <= bufferData.length; i++){
if (selectedRow + bufferData.length + i > newTreatmentData.length){ // adding objects to the array collection to avoid range error
newTreatmentData.addItem(null);
}
}
for (i = 1; i <= rowsToMove; i++){
newTreatmentData[selectedRow + bufferData.length + i] = ObjectUtil.copy(newTreatmentData[selectedRow + i]) //first move the rows to "give room" for pasting
newTreatmentData[selectedRow + bufferData.length + i].order = selectedRow + bufferData.length + i; //manually changing the "order" property, but it doesn't help
}
for (var j:int = 1; j <= bufferData.length; j++){ //paste the data from the buffer
newTreatmentData[selectedRow + j] = ObjectUtil.copy(bufferData[j-1])
newTreatmentData[selectedRow + j].order = selectedRow + j; //again changing the order property
}
newTreatmentData.refresh();
}
I solved it by changing the mx_internal_uid property of every object in the dataprovider ArrayCollection. It seems that AdvancedDataGrid checks it to see if rows are equal. I assumed (and you know what they say about assumptions) that an object's UID changes when you copy its value into another object (hence the U in UID ;) ).