Recognize previous random number - actionscript-3

i write a few lines codes that when i click on the button, a random number will be generated.
then a random child will be show up on the stage.
but i'm trying to when i click again on the button, the previous child has been removed and new child with new random number will be replaced.
how can i do that?
or how can i find out what's the previous random number?
function clkBtn(evt:MouseEvent):void
{
i=(Math.floor(Math.random()*10));
addChild(picP[i]);
removeChild(picP[?]);
}

Just save a reference to the DisplayObject you are adding to the stage and then remove it on the next time the click function is called.
var displayObject:DisplayObject = null;
function clkBtn(evt:MouseEvent):void {
if(displayObject)
removeChild(displayObject);
var i:int = Math.floor(Math.random()*10);
displayObject = picP[i];
addChild(displayObject);
}

Related

ActionScript 3: Adding multiple instances of the same object to the stage and removing each separately

I have a piece of code adding three insances of the same MovieClip to the stage. I also added MouseEvent.CLICK listener. Once any of the MovieClips gets clicked, I want it to be removed from the stage. My problem is, whenever any of the elements gets clicked, only the last one gets removed and when I click again on a different instance, I'm getting:
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
I added these three MovieClips to an array, but I don't know how I can properly identify which instance got clicked and remove only the said instance.
This is the excerpt of code I have:
var myMC: SomeMC;
var myArray: Array = [];
function Loaded(e: Event): void {
for (var i: int = 0; i < 3; i++) {
myMC = new SomeMC();
myMC.addEventListener(MouseEvent.CLICK, Clicked);
myMC.y = 50;
myMC.x = 50 * i;
addChild(myMC);
myArray.push(myMC);
}
}
function imageClicked(e: MouseEvent){
// Only the last instance gets removed.
e.currentTarget.parent.removeChild(myMC);
}
I'd be grateful for any help.
In Loaded function you create 3 instances of the object, but by doing:
myMC = new SomeMC();
you overwrite reference. In first iteration myMC is 1st one, in 2nd 2nd one, etc...
Then in imageClicked you're trying to remove it. 1st time it's working because it's referencing the last object, but after you removed it from stage it won't work anymore.
How about changing e.currentTarget.parent.removeChild(myMC); to e.currentTarget.parent.removeChild(e.currentTarget); ? That should remove clicked one.

Can i create a function to tell a button to open a movie clip of the same name

I am new to the actionscript side of flash,
I am working on a map that has say 20 popups(movieclips) and the countries are the buttons, i have just been informed i need to add 60 more.
Below is an example of the code i have been using
english_movie.visible=french_movie.visible=turkish_movie.visible=false
english_btn.addEventListener(MouseEvent.CLICK, englishButtonClick);
french_btn.addEventListener(MouseEvent.CLICK, frenchButtonClick);
turkish_btn.addEventListener(MouseEvent.CLICK, turkishButtonClick)
function englishButtonClick(event:MouseEvent):void {
english_movie.visible=true;
english_movie.play();
french_movie.visible=turkish_movie.visible=false
}
function frenchButtonClick(event:MouseEvent):void {
french_movie.visible=true;
french_movie.play();
english_movie.visible=turkish_movie.visible=false
}
function turkishButtonClick(event:MouseEvent):void {
turkish_movie.visible=true;
turkish_movie.play();
english_movie.visible=french_movie.visible=false
}
Im thinking there must be an easier way to do this than replicating the code over and over.
Any help would be much appreciated.
Here's how to simplify the whole thing with code: Each btn object is
related to one movie object. This can be achieved with a Dictionary.
var btnToMovieAssociation:Dictionary = new Dictionary();
btnToMovieAssociation[english_btn] = english_movie; // repeat this line for every btn/movie pair
Now you have to generalise your click handler. The key difference
between each function (apart from making one certain movie visible)
is that they all make certain other movies invisible. But actually,
it's sufficient to only make the previously visible movie invisble.
To do this, create a variable that keeps track of the current visible
movie.
var currentMovie:MovieClip = english_movie;
Initialising the variable with english_movie has no effect on the
program. you can pick any other of the movies. It will make things
easier in the following code if this variable is initialised.
Now your function does effectively this:
make movie of clicked button visible
play this movie
make last movie invisible
Here's the cool part. You only add one listener. Look up if something
is in the dictionary for the clicked thing and consider that the
movie you want to show next.
addEventListener(MouseEvent.CLICK, buttonClick);
function buttonClick(event:MouseEvent):void
{
var movie:MovieClip = btnToMovieAssociation[event.target]
if (movie == null)
return; // nothing in the dictionary, it wasn't a button that was clicked.
movie.visible=true;
movie.play();
currentMovie.visible = false;
currentMovie = movie;
}
There are problems with this solution:
You still have to declare every pair, which is still tedious and prone to erro. (you have to type every name twice)
If your buttons are made up of several objects, event.target might point to them instead of the button as a whole. But with only
the btns in the dictionary and not all their individual parts,
nothing would be found in the dictionary. This can be circumvented by
setting mouseChildren = false; on every btn.
i posted this question else where and got this response
var tl:MovieClip=this;
var mc:MovieClip;
var i:int;
var buttonA:Array=[english_btn,french_btn,turkish_btn];
for(i=0;i<buttonA.length;i++){
buttonA[i].addEventListener(MouseEvent.CLICK,buttonF);
tl[buttonA[i].name.split("_")[0]+"_movie"].visible = false;
}
function buttonF(e:MouseEvent):void{
for(i=0;i<buttonA.length;i++){
tl[buttonA[i].name.split("_")[0]+"_movie"].visible = false;
}
tl[e.currentTarget.name.split("_")[0]+"_movie"].visible=true;
}
Which works great.

Add event listener to the items in an array

I have an array with movieclips (r1, r2 etc) which are placed on stage dynamically every time there is a hittestobject. I want to add event listener to those movieclips in the array so that every time there is a click on them the last item to be removed. I have this code but it seems to be wrong because only the first element of the array is remove. Can you please help me?
var counter:int = 0;
function releaseToDrop(e:MouseEvent):void
{
Star(e.target).stopDrag();
if (Star(e.target).hitTestObject(target))
{
removeChild(Star(e.target));
var replace:Array = [r1,r2,r3,r4,r5,r6,r7,r8]
addChild(replace[counter]);
counter = counter+1;
}
else
{
trace("No collision.");
removeChild(Star(e.target));
}
}
replace[counter].addEventListener("click", bindClick(o));
function bindClick(o)
{
replace.splice(replace.indexOf(replace[counter]),1);
trace(counter);
}
For one, your bindClick function is inside the releaseToDrop function. This way that function will not be called. Also, try to use the static refence for the click event, so MouseEvent.Click instead of "click".
For your convenience, trace the current state of "counter" in the bindClick function, so you know what element will be removed. You will probably then find out where the flaw is in your logic.
A wise thing to to is also to check counter is not outside the scope of your array. So in bindClick, check for counter < replace.length. (for that the replace array of course has to be defined outside of the function scope of releaseToDrop.
Hope this gets you working in the right direction.
For future references adding addEventListener to the elements of an array so that every time there is a click on them the last item to be removed can be done by this code:
import flash.display.Sprite;
var replace:Array = [r1,r2,r3,r4,r5,r6,r7,r8]
var counter:int = 0;
// Every time there is a hittestobject an element of the array is placed on stage
function releaseToDrop(e:MouseEvent):void
{
Star(e.target).stopDrag();
if (Star(e.target).hitTestObject(target))
{
removeChild(Star(e.target));
addChild(replace[counter]);
counter = counter+1;
trace(counter);
}
}
// The first element of the array has an eventListener and when is clicked the last item of that array shown on stage is removed
var yourSprite:Sprite=new Sprite();
replace.push(yourSprite);
replace[0].addEventListener(MouseEvent.CLICK, myClickHandler, false, 0, true);
function myClickHandler (e:MouseEvent):void
{
counter =counter-1;
if (contains(replace[counter]))
removeChild(replace[counter]);
trace(counter);
}
Can you add an event listener to every movie clip that you spawn, then in each event handler, add a conditional to check if the clicked movie clip is the last item, then remove it (or do whatever you need to to it).
You should also accept Chicken's advice.

Turn image array images to buttons AS3

I'm creating an app with a search function. I display the images by loading from the array the one's which match the search criteria. All the images are loaded from the library. I want to be able to click on an image as though it were a button. Once I click I want to goto frame 3 and change a variable integer to say which image was clicked on so that I can display the information about the photo in frame 3. Can I do this using an event listener say
imagesArray[i].addEventListener(MouseEvent.CLICK, imageClick);
function imageClick(event:MouseEvent):void
{
gotoAndStop(3);
current = i;
}
or similar,
Thanks
Yes, but it won't be as easy. First, Bitmaps do not process events, so you can't assign a listener directly to a Bitmap object. Next, there is no "i" available in such a construction, you have to determine that "i" by yourself. To do that, you parse event.target property, which is the object that's been clicked. You wrap each Bitmap object into a separate Sprite object, assign listeners to these sprites, then you parse event.target to get the relevant object reference out of it, grab the index via indexOf() call, and assign it to global current variable.
for (i=0;i<imageArray.length;i++) {
var sp:Sprite=new Sprite();
sp.addChild(imageArray[i]);
// position "sp" correctly here
addChild(sp);
sp.addEventListener(MouseEvent.CLICK, imageClick);
}
function imageClick(e:Event):void {
var content=e.target.getChildAt(0); // the object that was wrapped
var i:int=imageArray.indexOf(content);
if (i==-1) return; // OW, out of array
current=i;
gotoAndStop(3);
}
I'm not so sure that setting "current" to "i" would work as the function wouldn't be running at the same time as the for loop.
I'm assuming that because you're using the [i] that you've added the event listeners in a for loop?
What you could do is:
for (var i:int = 0; i < (howeverManyTimesToRun); i++)
{
imagesArray[i].addEventListener(MouseEvent.CLICK, imageClick);
imagesArray[i].myIndex = i;
}
And then in your function (outside of the for loop)
function imageClick (e:MouseEvent) {
gotoAndStop(3);
current = e.currentTarget.myIndex;
}
Also in your for loop you might want to add
imagesArray[i].buttonMode = true;
To change the mouse cursor to a hand when their mouse goes over your image.

ActionScript 3 name property is not returning the right name...?

I experienced a problem with the name property in as3, I created this "dot" movieclip and I exported to a class,
then I anonymously created a bunch of dots using a loop. I assigned numbers as name to each dots
private function callDots(num:Number):void
{
for (var i = 0; i < subImagesTotal[num]; i++)
{
var d:Dot = new Dot();
d.x = i*23;
d.y = 0;
d.name = i;
dotContainer.addChild(d]);
}
}
so far so good, I checked that if I trace the name here, I will get the number I want.
However, it's not giving me the numbers if I trace it in other functions.
I added all of my dots to "dotContainer", and if I click on one of the dots, it will call this function
private function callFullSub(e:MouseEvent):void
{
var full_loader:Loader = new Loader();
var temp:XMLList = subImages[sub];
var full_url = temp[e.target.name].#IMG;
full_loader.load(new URLRequest(full_url));
full_loader.contentLoaderInfo.addEventListener(Event.INIT, fullLoaded);
}
e.target.name is suppose to be numbers like 1 or 2, but it's giving me "instance66" "instance70" and I
have no idea why. Because I did the same thing with loaders before and it totally worked.
Any ideas? Thanks.
christine
The e.target returns the inner most object clicked on, this could be a TextField, another MovieClip or posibly a shape (I'm not 100% of the last one) inside the "Dot".
To prevent this you could try to set the mouseChildren property to false on the Dot's when you add them. This should insure that nothing inside the dots can dispatch the click event, and thus the Dot's should do it.
Perhaps you could also in the event handler verify the target type with code like this:
private function callFullSub(e:MouseEvent):void
{
if(!e.target is Dot)
throw new Error("target in callFullSub is not Dot but: " + e.target.toString());
//The rest of you code here
}
The answer is [e.currentTarget.name] I perform this all the time!
Should return "Dot1" "Dot2", etc.
If the value you wish to return is a number or other data type other than a string (name of object) use [e.currentTarget.name.substr(3,1).toString()]
Should return 1, 2, etc.
Navee
I tried to reproduce your problem first with Flex using runtime created movieClips and then with Flash using Dot movieClip symbols exported for ActionScript. Neither application exhibited the problem.
You may already know names like "instance66" "instance70" are default enumerated instance names. So, whatever is dispatching the MouseEvent is NOT the dot instance. Perhaps you are unintentionally assigning callFullSub to the wrong targets, maybe your containers? Try assigning it to dot instance right after you create them, like this:
private function callDots(num:Number):void
{
for (var i = 0; i < subImagesTotal[num]; i++)
{
var d:Dot = new Dot();
d.x = i*23;
d.y = 0;
d.name = i;
d.addEventListener(MouseEvent.CLICK, callFullSub);
dotContainer.addChild(d]);
}
}
Be sure to temporarily comment out your original assignment.
Try this might work,..
d.name = i.toString();
You have not shown enough of your code for me to be able to give you a DEFINATE answer, I will however say this.
//After you create each loader you need to set its mouseEnabled
//property to false if you do not want it to be the target of
//Mouse Events, which may be superseding the actual intended target;
var full_loader:Loader = new Loader();
full_loader.mouseEnabled = false;
//Also you could name the loaders and see if what comes back when you click is the same.
ALSO! Add this to your Mouse Event handler for CLICK or MOUSE_DOWN:
trace(e.target is Loader); //If traces true you have an answer
I believe that the mouse events are being dispatched by the Loaders.
please provide more of your code, the code where the Loader.contentLoaderInfo's COMPLETE handler fires. I assume this is where you adding the loaders to the display list as I cannot see that now.