Disabling Nested MovieClips After Removing Parent Movieclip - actionscript-3

In some of the level MovieClips I have for my Flash game, there is a certain MovieClip that controls a custom-built camera that I've created. Both the camera and the MovieClip function correctly and smoothly. However, whenever a level is completed and removed from the game, I get an Error #1009 not recognizing the checkCameraZoom function. Also, this MovieClip is not added dynamically with code, but rather placed in the specified level MovieClips from the Library before run-time. Is there any possible way to fix this error?
ZoomOutArea Class:
package com.engine.assetHolders
{
import com.engine.documentClass.*;
import flash.display.*;
import flash.events.*;
public class ZoomOutArea extends MovieClip
{
public function ZoomOutArea():void
{
this.visible = false;
this.addEventListener(Event.ADDED_TO_STAGE, initZoomOutArea);
// constructor code
}
public function initZoomOutArea(event:Event):void
{
this.addEventListener(Event.ENTER_FRAME, checkCameraZoom);
}
public function checkCameraZoom(event:Event):void
{
if (Document.getInstance != null)
{
if (this.hitTestObject(MovieClip(parent.parent).player.playerHitArea))
{
this.hitTestZoom(0.6);
}
if (! this.hitTestObject(MovieClip(parent.parent).player.playerHitArea))
{
this.hitTestZoom(1);
}
}
}
public function hitTestZoom(zoomLevel):Number
{
MovieClip(parent.parent).cameraScale = zoomLevel;
return zoomLevel;
}
}
}

You register the class for ENTER_FRAME events when it's added to the stage, but you never unregister it. So that's why it keeps going even after it has been removed from the stage, and has no parent anymore.
You could add another listener for Event.REMOVED_FROM_STAGE and then remove the checkCameraZoom listener:
public function initZoomOutArea(event:Event):void
{
this.addEventListener(Event.ENTER_FRAME, checkCameraZoom);
this.addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
}
private function onRemoved(event:Event):void
{
this.removeEventListener(Event.ENTER_FRAME, checkCameraZoom);
}

Related

how to pause multiple symbols with mouse click in flash AS3

I have been using actionscript 3 to control my animations,
I can play and reset the video but not able to pause globally.
There are totally 3 symbols,
1st Parent movieclip
2nd child moviclip with animation--> I am able to pause this.
3rd child movieclip with animation--> I am unable to pause this
Script
package lib {
import flash.display.MovieClip;
import flash.events.*;
public class Controlstry extends MovieClip {
public function Controlstry() {
// constructor code
addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(evt=null)
{
if(video_mc != null)
{
playBtn.addEventListener(MouseEvent.MOUSE_DOWN, playVideo);
pauseBtn.addEventListener(MouseEvent.MOUSE_DOWN, pauseVideo);
replayBtn.addEventListener(MouseEvent.MOUSE_DOWN,replayVideo);
}
}
private function playVideo(evt:MouseEvent)
{
if(video_mc.currentFrame == video_mc.totalFrames)
{
video_mc.gotoAndPlay(2);
}
else
{
video_mc.play();
}
}
private function pauseVideo(evt:MouseEvent)
{
video_mc.stop();
}
private function replayVideo(evt:MouseEvent)
{
video_mc.gotoAndPlay(2);
}
}
}
It's not very clear from your code as to what are the three movie clips which you want to control.
Assuming you have 3 movie clips nested into each other, you can call stop() on each one of them to stop their animation (assuming they have a timeline animation)
So if your structure looks like this : a-->b-->c, where a is the parent, b a child of a, and c a child of b, you can call
a.stop();
a.b.stop();
a.b.c.stop();
This is obviously assuming the fact that you have instance names declared for the child properties in the IDE.
Hope this helps.
EDIT:
As per your sent FLA, you should do the following steps to achieve what you want:
Go inside video_mc on your stage, and select Layer 9, and give it an instance name of 'backgroundMC'.
Modify your script like this:
package lib {
import flash.display.MovieClip;
import flash.events.*;
public class Controlstry extends MovieClip {
public function Controlstry() {
// constructor code
addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(evt:Event=null)
{
if(video_mc != null)
{
playBtn.addEventListener(MouseEvent.CLICK, playVideo);
pauseBtn.addEventListener(MouseEvent.CLICK, pauseVideo);
replayBtn.addEventListener(MouseEvent.CLICK,replayVideo);
}
}
private function playVideo(evt:MouseEvent)
{
if(video_mc.currentFrame == video_mc.totalFrames)
{
video_mc.gotoAndPlay(2);
video_mc.backgroundMC.gotoAndPlay(1);
}
else
{
video_mc.play();
video_mc.backgroundMC.gotoAndPlay(1);
}
}
private function pauseVideo(evt:MouseEvent)
{
video_mc.stop();
video_mc.backgroundMC.gotoAndStop(1);
}
private function replayVideo(evt:MouseEvent)
{
video_mc.gotoAndPlay(2);
video_mc.backgroundMC.gotoAndPlay(1);
}
}
}
A couple of things to note here:
Use MouseEvent.CLICK if you want it to respond to click events. You had used MouseEvent.DOWN
Always give events a type like evt:Event and not just evt=null.
if(video_mc != null) can be easily checked by if(video_mc).
Hope this answers the question.

AS3 | 1120: Access of undefined property stage

My goal is to create rectangle as MovieClip with stage size, but Flash gives me this error: 1120: Access of undefined property stage. (on line 6,7,14)
My code:
package {
import flash.display.MovieClip;
public class main {
var mc_background:MovieClip = new MovieClip();
var stageW:Number = stage.stageWidth;
var stageH:Number = stage.stageHeight;
public function main() {
drawBackground();
}
public function drawBackground():void {
mc_background.beginFill(0xFF00CC);
mc_background.graphics.drawRect(0,0,stageW,stageH);
mc_background.graphics.endFill();
stage.addChild(mc_background);
}
}
}
i had a similar problem, the thing is, the stage hasn't really been setup yet, so you need to wait to get data from it or stuff in it. just add this:
protected function addedToStageHandler(event:Event):void
{
//do stuff
}
protected funcion init():void
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
//more stuff
}
hope it helps
The stage property of an object isn't defined until the object has been added to the Stage or another object on the Stage.
The constructor of a class is called when the class instance is created, and that is before the instance could have been added to the Stage. So, you can't access stage within code you call from the constructor, or when you define the instance variables stageW and stageH.
To access the stage property as soon as the object is added to the stage, allow the object to handle the ADDED_TO_STAGE event:
package {
import flash.display.MovieClip;
import flash.events.Event;
public class main
{
var mc_background:MovieClip = new MovieClip();
public function main()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler(event:Event):void
{
// Generally good practice to remove this listener from the object now because it stops addedToStageHandler from being called again if the object is removed and added back to the stage or display list.
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
drawBackground();
}
private function drawBackground():void {
mc_background.beginFill(0xFF00CC);
mc_background.graphics.drawRect(0,0,stage.stageWidth, stage.stageHeight);
mc_background.graphics.endFill();
addChild(mc_background);
}
}
}

ActionScript 3 Event doesn't work

I'm new in AS, and trying to make my first application. I have a class, that showld manage some events, like keyboard key pressing:
public class GameObjectController extends Sprite
{
var textField:TextField;
public function GameObjectController()
{
addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function onKeyDown(event: KeyboardEvent):void
{
trace("123");
}
}
but when I'm running it, and pressing any button, nothing happands. What am I doing wrong?
Try stage.addEventListener() for KeyboardEvents.
The reason for this is that whatever you add the event to needs focus, and the stage always has focus.
If GameObjectController isn't the document class, it will need to have stage parsed to its constructor for this to work, or it will need to be added to the stage first. The former will be less messy to implement.
public function GameObjectController(stage:Stage)
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
Add the keyboard event to the stage and import the KeyboardEvent class.
package
{
import flash.display.Sprite;
import flash.events.KeyboardEvent;
public class GameObjectController extends Sprite
{
public function GameObjectController()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownEventHandler);
}
private function keyDownEventHandler(event:KeyboardEvent):void
{
trace(event);
}
}
}

AS3 Cannot access stage from custom class

How can I access the stage and especially the width and mouse position of the flash Movie from a custom class?
package classes
{
import flash.events.*;
import flash.display.*;
public class TableManager extends Sprite
{
public function TableManager() {
sayStage();
}
public function sayStage():void
{
trace(stage);
}
}
}
This will only return nill. I know that DisplayObjects don't have any stage until they have been initiated so you can't access the stage in your constructor but even if I call sayStage() later as an instance method it won't work.
What am I doing wrong?
If TableManager is on the stage you can access the stage with this.stage.
The trick is you have to wait for the instance to be added to the stage. You can listen for the ADDED_TO_STAGE event so you know when that's happened.
package classes {
import flash.events.*;
import flash.display.*;
public class TableManager extends Sprite {
public function TableManager() {
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
sayStage();
}
public function sayStage():void {
trace(this.stage);
}
}
}
The most defensive way to write this is:
public function TableManager() {
if(this.stage) init();
else this.addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
if(e != null) this.removeEventListener(Event.ADDED_TO_STAGE, init);
sayStage();
}
If the object is already on the stage at the time of initialization, then immediately call the init function with no arguments. If not wait until its been added to the stage. Then when the init function gets called, if it was called as the result of an event, then detach the event handler, and move along.
You can pass a reference of the root movieclip (i.e. the stage) to your custom class.
e.g.
package classes
{
import flash.events.*;
import flash.display.*;
public class TableManager extends Sprite
{
private var _rootMC:MovieClip;
public function TableManager(rootMC:MovieClip) {
_rootMC = rootMC;
sayStage();
}
public function sayStage():void
{
trace(_rootMC.stage);
trace(_rootMC.stage.stageWidth);
}
}
}
Then when instantiating your instance of TableManager from the root timeline:
//the keyword 'this' is the root movieclip.
var newTM:TableManager = new TableManager(this);
stage will be null as long as the Sprite hasn't been added to the display list - it's nothing to do with initiation. E.g.
var t:TableManager = new TableManager;
stage.addChild( t ); // or your root class, or any class that's already on the displaylist
trace( t.stage ); // [Stage stage]
t.parent.removeChild( t );
trace( t.stage ); // null
As #crooksy88 suggests, either pass in the stage to the constructor, or keep it as a static somewhere, say your main document class, so that you can access it everywhere.
i think usefull for You should be create static reference to stage :
in Your main class add line and set stage :
public static var stage:Stage;
...
public function Main():void { // constructor
Main.stage = stage;
...
and than in custom class :
public function sayStage():void
{
trace(Main.stage);
trace(Main.stage.stageWidth);
}
you may access this.stage when the current object(also a sprite) is already attached to the stage.
public class TableManager extends Sprite{
public function TableManager()
{
}
public function sayStage():void
{
trace(stage);
}
}
TableManager tm=new TableManager();
//tm.sayStage(); // no
addChild(tm);
tm.sayStage(); // fine
hope this could help
here is a pretty good solution you only need to reference the stage inside your class you just pass it as a simple object, here how to do that
package {
public class Eventhndl{
private var obj:Object;
public function Eventhndl(objStage:Object):void{
obj = objStage;
trace(obj); // now the obj variable is a reference to the stage and you can work as normal you do with stage (addChild, Events Etc..)
}
}
this is how you make instance to run it, i have used the constructor method but you can change it to any function as you wish and call it whenever you need it.
import Eventhndl;
var EH:Eventhndl = new Eventhndl(stage);
here is some few Examples how to access stage from class
https://stackoverflow.com/a/40691908/1640362
https://stackoverflow.com/a/40691325/1640362

Actionscript 3 mouse_over play movie

I'm trying to play a movie clip when I mouse_over it. I can do it fine by doing:
mc1.addEventListener(MouseEvent.MOUSE_OVER,mover);
function mover(e:MouseEvent):void {
mc1.play();
}
But, I want to use the same function for other movie clips, for example, to play movieclip2, movieclip3 etc.
How would I achieve this?
mc1.addEventListener(MouseEvent.MOUSE_OVER,mover);
mc2.addEventListener(MouseEvent.MOUSE_OVER,mover);
mc3.addEventListener(MouseEvent.MOUSE_OVER,mover);
function mover(e:MouseEvent):void {
e.currentTarget.play();
}
You can make a class to encapsulate your logic for example, to access the MovieClip from the calling function, use the property of the Event object
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class PlayMovieClip {
// register the mouse over event with whatever MovieClip you want
public static function register(mc:MovieClip):void{
mc.addEventListener(MouseEvent.MOUSE_OVER,mover);
}
// unregister the event when you dont need it anymore
public static function unregister(mc:MovieClip):void{
mc.removeEventListener(MouseEvent.MOUSE_OVER, mover);
}
// the MouseEvent will be throw whenever the mouse pass over the registered MovieClip
// and in the MouseEvent property you have the targeted object
// so use it
public static function mover(e:MouseEvent):void{
// check if we have really a MovieClip
var mc:MovieClip=e.currentTarget as MovieClip;
if (mc!==null) {
// we have a MovieClip so we can run the function play on it
mc.play();
}
}
}
usage:
PlayMovieClip.register(mc1);
...
PlayMovieClip.register(mcX);
and to remove the event:
PlayMovieClip.unregister(mc1);
...
PlayMovieClip.unregister(mcX);