MovieClip not reacting how I intended on rollover - actionscript-3

I thought I had it but I am still not able to get my movieClip to play(). I am getting the trace that its making it into the "updateBomb" function on rollover but my currentBomb is not going to frame 2 and playing. Any ideas why this is happening? Could it be because my movieclips are in a container MC?
function getStarted(event:MouseEvent){
startClip.removeEventListener(MouseEvent.ROLL_OVER, getStarted);
for (var i:int = 1; i < 11; i++) {
var currentBomb:MovieClip = bombClip["bomb_" + i];
trace(currentBomb);
currentBomb.addEventListener(MouseEvent.ROLL_OVER, function (evt:MouseEvent):void { updateBomb(currentBomb); });
}
bombClip.play();
}
function updateBomb(currentBomb:MovieClip):void {
trace("in update bomb");
trace(currentBomb);
currentBomb.gotoAndPlay(2);
}
I added a trace currentBomb in updateBomb and this is what I get
[object bombNum1_5]
in update bomb
[object bombNum1_5]
in update bomb
[object bombNum1_5]
in update bomb
[object bombNum1_5]
in update bomb
[object bombNum1_5]
in update bomb
[object bombNum1_5]
When I rollover different bombs. Do I need to reference the bombs by name?

You are adding an event listener using an anonymous function, creating a closure by storing the currentBomb in the mouse roll over handler.
However, that currentBomb variable is being changed in the loop. And each anonymous function has a reference to it. So when you mouse over each movie clip, they all point to the same bomb (the last one in the loop).
Instead of using the anonymous function, just add an event listener like below. The event handler can rely on the fact that the event came from a MovieClip and call it's gotoAndPlay() method:
// inside the for loop...
currentBomb.addEventListener(MouseEvent.ROLL_OVER, updateBomb);
// roll over event handler
function updateBomb(event:MouseEvent):void
{
var currentBomb:MovieClip = event.target as MovieClip;
if (currentBomb) // is null if above line fails
currentBomb.gotoAndPlay(2);
}

Related

using an array function for click events

I have created symbols which contain animations (mc1 - mc25). I would like to play these animations if I click on the symbols (click on mc1 -> play mc1, click on mc2 -> play mc2 etc.).
I created an array to address all my symbols in one go. It works ok.
var A:Array = [mc1, mc2, mc3, mc4,...mc25] // create array
car aClip:MovieClip;
for each (aClip in A) // stop all symbols
{aClip.stop();}
How can I get to the result below for all my symbols using an array function?
mc1.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler_4);
function fl_MouseClickHandler_4(event:MouseEvent):void
{
mc1.play();
}
I tried something like this but I couldn't get it work:
aClip.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
function fl_MouseClickHandler(event:MouseEvent):void {
aClip.play();
}
Thank you!
The simple way about it is to algorithmically figure which one was clicked. The script below is short and does not contain various checks, it assumes all the elements of A are really MovieClips.
// Assume, you filled the Array with these clips already.
var A:Array;
// Iterate all the clips.
for each (var aClip:MovieClip in A)
{
// Subscribe to each of the clips for the CLICK event.
aClip.addEventListener(MouseEvent.CLICK, clickPlay);
}
// Click event handler function. The point is, you can subscribe it
// to the multiple objects and use the function argument to figure out
// which one of them all is actually the source of the event.
// Furthermore, you can subscribe it to handle multiple events too,
// the argument also carries the id of the event. Sometimes it is
// really simpler to compose a single event-processing gate
// rather then process each one event in a separate handler.
function clickPlay(e:MouseEvent):void
{
// Use e.currentTarget because the initial e.target
// could be not the MovieClip itself, but some interactive
// element deep inside the MovieClip's hierarchy.
// Read about bubbling events (MouseEvent is bubbling)
// to get the whole picture of it.
// Typecasting, because e.target and e.currentTarget
// are of base Object type.
var aClip:MovieClip = e.currentTarget as MovieClip;
// Well, the only thing that is left.
aClip.play();
}

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.

Clicking on a movieclip inside another movieclip on AS3

Alright, what i need it's simple but its driving me crazy, i want to know if AS3 detects my mouse inside a movieclip.
For example, i have a movieclip instanced "BEframes" which is inside movieclip "BE1" and i want to put him inside a new movieclip instanced "roll". So the order would be roll > BE1 > BEframes.
I want to know if flash will only detect "roll" or he will detect all movieclips, thank you,
for(i=1;i<=77;i++){
var str:String =("BE" + i);
this[str].BEframes.gotoAndStop(i);
this[str].addEventListener(MouseEvent.CLICK, clique);
this[str].addEventListener(MouseEvent.ROLL_OVER, over);
this[str].addEventListener(MouseEvent.ROLL_OUT, out);
}
function clique(evt:MouseEvent):void{
var botao:String = evt.currentTarget.name.toString();
var num:String = botao.replace("BE", "");
parede_esquerda.gotoAndStop(num);
}
function out(evt:MouseEvent):void {
evt.currentTarget.gotoAndPlay("out");
}`enter code here`
function over(evt:MouseEvent):void {
evt.currentTarget.gotoAndPlay("over");
}
*
Probably, you should use MOUSE_OVER and MOUSE_OUT instead of ROLL_OVER and ROLL_OUT.
this[str].addEventListener(MouseEvent.MOUSE_OVER, over);
this[str].addEventListener(MouseEvent.MOUSE_OUT, out);
To avoid receiving mouseEvent for movieClips set mouseEnabled to false, i.e if you don't want clip roll's mouse event setroll.mouseEnabled = false so that the object below will receive mouseEvent

EnterFrame handler to run only while timeline is stopped on a certain frame

I have some code in a frame. It's basically
this.addEventListener(Event.ENTER_FRAME, handleUpdate);
function handleUpdate(e:Event):void
{...}
I want the code to be executed only when on that frame. But the handleUpdate function keeps getting called even when I'm out of that frame.
The timeline is stopped on this frame, and I want the handleUpdate to run continuously until the timeline moves off the frame.
If you're set on having the code for this on the frame in question, then you could do this:
var tmpCurFrame:int = currentFrame; //store the current frame
this.addEventListener(Event.ENTER_FRAME, handleUpdate)
function handleUpdate(e:Event):void {
if (tmpCurFrame != currentFrame) { //if the frame has changed, stop the frame handler
this.removeEventListener(Event.ENTER_FRAME, handleUpdate);
return;
}
//do your code
}
handleUpdate(null);
As an aside, it's much cleaner to have a document class and other class files that manage this sort of thing instead of using frame scripts. But if you all you're looking for is a quick and dirty tweak to your existing code, this should do the trick.
Haven't you heard about addFrameScript ?
It's perfect for your needs.
var desiredFrame = 25; // Timeline frame (starts from 1)
this.addFrameScript(desiredFrame-1, onFrame25); // 1st param is zero-based
function onFrame25():void
{
trace("I'm on frame", desiredFrame);
}
There's a few things you should consider with your approach:
Adding an ENTER_FRAME listener on the frame you care about happens after you enter that frame, so if the movieclip is playing you won't get an ENTER_FRAME event until the next frame (at which time it may have moved off that frame).
Be aware that code on a frame executes every time the playhead enters that frame, and you should be careful to remove listeners when appropriate for memory leak purposes.
So one approach would be to place this code on the frame in question - note that it also nicely removes its listener:
var thisFrame:int = currentFrame;
function handleUpdate(e:Event) {
if (currentFrame==thisFrame) {
// your code here...
} else {
// remove listener if we moved off the frame
removeEventListener(Event.ENTER_FRAME, handleUpdate);
}
}
// call it now because the listener won't fire until next frame
handleUpdate(null);
// add listener in prep for next ENTER_FRAME, though note that
// if we move off this frame, then the listener is removed above
addEventListener(Event.ENTER_FRAME, handleUpdate);
Another approach would be adding the following code on frame 1, so the listener always runs and is never cleaned up, and only performs the code when on frame 12:
addEventListener(Event.ENTER_FRAME, handleUpdate);
function handleUpdate(e:Event):void
{
if (currentFrame==12) {
// your code here...
}
}

actionscript error?

I have a problem, this works then at the " and" it dies and gives me an error
TypeError: Error #1009: Cannot access
a property or method of a null object
reference. at
Untitled_fla::MainTimeline/frameLooper()
at
flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
CODE
var string:String = "Welcome to PuppetWeb Inc\nMy name is Steve and I will be your host for this presentation!\n...\nOkay I think it is ready, let's go!";
var myArray:Array = string.split("");
var timer : Timer = new Timer (100, myArray.length);
timer.addEventListener (TimerEvent.TIMER, frameLooper);
timer.start();
function frameLooper(event:Event):void {
if(myArray.length > 0) {
text1.appendText(myArray.shift());
}else{
removeEventListener(Event.ENTER_FRAME, frameLooper);
}
}
It works for the start and then just dies at and, and then it shows that error about 50 times and restarts.
Any help?
I assume this is code written on a keyframe in the timeline, so my guess would be that your textfield goes away for some reason, most likely a keyframe animation of some kind.
It's also somewhat odd that you are removing an Event.ENTER_FRAME listener when the array is empty and not the TimerEvent.TIMER
At the end, you're trying to remove the listener from an implicit "this". Your statement is equivalent to:
this.removeEventListener(Event.ENTER_FRAME, frameLooper);
But "this" is a reference to the main timeline (if this is a frame script on the main timeline) or a reference to the instance that contains this code. It's not a reference to the Timer instance, which is what you need:
event.target.removeEventListener(TimerEvent.TIMER, frameLooper);
Why not use string.charAt()?
var string:String = "Welcome to PuppetWeb Inc\nMy name is Steve and I will be your host for this presentation!\n...\nOkay I think it is ready, let's go!";
var timer : Timer = new Timer (100, string.length);
timer.addEventListener (TimerEvent.TIMER, frameLooper);
timer.start();
function frameLooper(event:TimerEvent):void {
text1.appendText(string.charAt (event.target.currentCount-1);
}
Among all the other issues Stated in the other posts you are not stopping the time.
Dont forget timer.stop( );