RemoveChild and Error 2025 - actionscript-3

I'd like to remove a child (background) via another class. I can't seem to be able to target it! It always returns me null or error 2025 and stuff... hehe.
I have the background in my class creationObjets:
package cem{
import flash.display.Sprite;
public class creationBackground extends Sprite{
public function creationBackground() {
switch(monterJeu._Difficulte){
case 0:
backgroundFacile();
break;
case 1:
backgroundMoyen();
break;
case 2:
backgroundDifficile();
break;
}
}
private function backgroundFacile():void{
var backgroundStage:Sprite = new Sprite();
backgroundStage.graphics.beginFill(0x8FCCA8);
backgroundStage.graphics.moveTo(0,0);
backgroundStage.graphics.lineTo(750,0);
backgroundStage.graphics.lineTo(750,450);
backgroundStage.graphics.lineTo(0,450);
backgroundStage.graphics.lineTo(0,0);
backgroundStage.graphics.endFill();
this.addChild(backgroundStage);
}
private function backgroundMoyen():void{
var backgroundStage:Sprite = new Sprite();
backgroundStage.graphics.beginFill(0x8F3378);
backgroundStage.graphics.moveTo(0,0);
backgroundStage.graphics.lineTo(750,0);
backgroundStage.graphics.lineTo(750,450);
backgroundStage.graphics.lineTo(0,450);
backgroundStage.graphics.lineTo(0,0);
backgroundStage.graphics.endFill();
this.addChild(backgroundStage);
}
private function backgroundDifficile():void{
var backgroundStage:Sprite = new Sprite();
backgroundStage.graphics.beginFill(0x233378);
backgroundStage.graphics.moveTo(0,0);
backgroundStage.graphics.lineTo(750,0);
backgroundStage.graphics.lineTo(750,450);
backgroundStage.graphics.lineTo(0,450);
backgroundStage.graphics.lineTo(0,0);
backgroundStage.graphics.endFill();
this.addChild(backgroundStage);
}
}
}
public static var _creationBackground:creationBackground = new creationBackground();
below, I add it:
addChild(_creationBackground);
then I want to remove it from another class actionObjets! How can I get to my background?
I tried
creationObjets._creationBackground.parent.removeChild(creationObjets._creationBackground);
removeChild(creationObjets._creationBackground);
I really have no idea how to access it!

I'm not sure if I understand your problem correctly but:
Remember that in order to remove a child you need access to the child's stage. If your actionObjects class is a Movieclip or sprite it will have a read-only variable that will reference the stage (which may or may not be the same as the stage you added _creationBackground too).
So for instance:
stage.removeChild(_creationBackground);
Should work fine if actionObjets has the same stage as wherever you added _creationBackground.
If actionObjets does not have the same stage or has none at all (maybe it isn't a sprite or movieclip?) You can pass in the stage where _creationBackground was added.
IE:
package {
import flash.display.Stage;
public class actionObjets {
private var myStage:Stage;
public function actionObjets(s:Stage) {
myStage = s;
}
}
}
and then try:
myStage.removeChild(_creationBackground);
This is of course assuming that you have access to the _creationBackground clip inside actionObjets.
Not sure if this addressed your problem or not,
good luck.

Any of the following should suffice:
creationObjets.removeChild(creationObjet.getChildAt(0));
or
creationObjets.removeChild(creationObjet.getChildByName("creationBackground"));
or
creationObjets.removeChildAt(0);
When you use removeChildAt() or getChildAt() you must specify the display object's(that you want to get or remove) index position. The index position is the position of the display object in the display list of the display object container(I've made the assumption that its 0).
Also when using getChildByName() you must specify the name of the display object that you want to get. Note that you must set the name property of the display object first.
Here's a working example based on you flash app/movie:
package
{
import cem.CreationObjet;
import cem.ActionObjet;
import flash.display.MovieClip;
public class Main extends MovieClip
{
public function Main():void
{
init();
}// end function
private function init():void
{
var creationObjet:CreationObjet = new CreationObjet();
addChild(creationObjet);
var actionObjet:ActionObjet = new ActionObjet(creationObjet);
}// end function
}// end class
}// end package
In the document class Main, first CreationObjet and ActionObjet is imported. Next an instance of the CreationObjet is declared, instantiated and added to the stage. Lastly an instance of the ActionObjet is declared, instantiated and the instance of CreationObjet is parsed as its only argument.
package cem
{
import cem.CreationBackground;
import flash.display.Sprite;
public class CreationObjet extends Sprite
{
private var _creationBackground:CreationBackground;
public function CreationObjet():void
{
_creationBackground = new CreationBackground();
addChild(_creationBackground);
}// end function
}// end class
}// end package
In the CreationObjet class, an instance of CreationBackground is added to the CreationObjet display object.
package cem
{
import cem.CreationObjet;
public class ActionObjet
{
private var _creationObjet:CreationObjet;
public function ActionObjet(p_creationObjet:CreationObjet):void
{
_creationObjet = p_creationObjet;
_creationObjet.removeChild(_creationObjet.getChildAt(0));
// or _creationObjet.removeChild(_creationObjet.getChildByName("creationBackground"));
// or _creationObjet.removeChildAt(0);
}// end function
}// end class
}// end package
Finally in ActionObjet class, the CreationBackground display object is removed from the CreationObjet.
I've had to make a bunch of assumptions about your flash app/movie, but this should give you a general idea of how to implement what I suggested before.
I hoped this helped :)

Related

AS3 Access a method inside the Main class from another class . Gives error?

I have trouble with actionScript , im trying to use a simple one line code to access a method inside the Document Class (Main) , but every time i got error . i tried the same code with a movieClip on stage, it work nicely .
Main Class linked to the fla :
package {
import flash.display.*;
import flash.events.*;
public class Main extends MovieClip {
public function Main() {
if (stage) {
init();
}
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
button.addEventListener(MouseEvent.CLICK,_click);
}
private function _click(e:MouseEvent):void {
var l:Leecher = new Leecher();
l.leech();
}
public function callMe():void {
trace("hey nice work");
}
}
}
Leecher Class :
package {
import flash.display.*;
public class Leecher extends MovieClip {
public function leech():void
{
trace(" leech function ");
Main(parent).callMe(); // output null object
Main(root).callMe(); // output null object
Main(Main).callMe(); // output null object
}
}
}
The Same code , but the class linked to a button on stage
package
{
import flash.display.*;
import flash.events.*;
public class Button extends MovieClip {
public function Button() {
this.addEventListener(MouseEvent.CLICK,r_click);
}
private function r_click(e:MouseEvent):void {
var l:Leecher = new Leecher();
l.leech();
Main(parent).callMe(); // hey nice work
Main(root).callMe(); // hey nice work
Main(Main).callMe(); // output null object
}
}
}
The errors are because when that code runs, the Leecher instance has not yet been added to the display list, and as such does not have a parent or root or stage (so parent is null).
Here is a breakdown of what's happening (explained with code comments):
private function _click(e:MouseEvent):void {
//you instantiate a new Leecher object
var l:Leecher = new Leecher();
//you call leech, but this new object does not have a parent because you haven't added it to the display list (via `addChild(l)`)
l.leech();
}
//your saying parent should be of type Main, then call the callMe method. However, parent is null because this object is not on the display list
Main(parent).callMe();
//same as above, except using root
Main(root).callMe();
//Here you are saying the Main class is of type Main (which since Main is a class and not an instance of Main will error or be null)
Main(Main).callMe();
The root, parent & stage vars of a display object are only populated when said display object is added to to the display list. In the case of root & stage the parent (and any grand parents) must also be added so that the top most parent/grandparent is the stage.
As a result, you need to wait until it's safe to access parent by listening for the Event.ADDED_TO_STAGE event.
private function _click(e:MouseEvent):void {
var l:Leecher = new Leecher();
//call the leech method once the child has been added to the stage and has a parent value
l.addEventListener(Event.ADDED_TO_STAGE, l.leech, false, 0, true);
addChild(l);
}
If you do the above, you'll need to add an optional event parameter to the leech method or you'll get an error:
public function leech(e:Event = null):void
{
To make your Main class easily accessible, you could use a static reference.
Static vars are not tied to an instance of an object, but to the class itself.
public class Main extends MovieClip {
//create a static var that holds a reference to the root/main instance
public static var main:Main;
public function Main() {
//assign the static var to this (the instance of Main)
main = this;
//...rest of code
If you do that, you can asses your root anywhere in your code by doing Main.main so in your example you could then do:
Main.main.callMe();
I'd recommend reading about static vars more before going crazy using them. Doing what I've just shown for an easy reference to your document class / root is safe, but in other contexts there are some memory & performance nuances it's best to be aware of.

Access of undefined property issues in AS3

I am having a bit of trouble with some AS3. First time using this language and have more experience with web development then OOP so am getting a bit confused.
I am trying to make it so that when someone clicks a 'powerbutton' which is a "movieclip" symbol within flash then another symbol should then become visible. This is all being done within the Kitchen class.
The code for the main class is which i got from a youtube tutorial video i followed;
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.events.Event;
import Kitchen
public class DragFood extends MovieClip
{
protected var originalPosition:Point;
var myKitchen:Kitchen
public function DragFood() {
myKitchen = new Kitchen;
originalPosition = new Point (x, y);
buttonMode = true;
addEventListener (MouseEvent.MOUSE_DOWN, down);
}
protected function down (event:MouseEvent):void
{
parent.addChild(this);
startDrag();
stage.addEventListener (MouseEvent.MOUSE_UP, stageUp);
}
protected function stageUp (event:MouseEvent):void
{
stage.removeEventListener (MouseEvent.MOUSE_UP, stageUp);
stopDrag();
if (dropTarget)
{
if(dropTarget.parent.name == "bowl")
{
trace("The " + this.name + " is in the bowl");
this.visible = false;
} else {
returnToOriginalPosition();
}
} else {
returnToOriginalPosition();
}
}
protected function returnToOriginalPosition():void
{
x = originalPosition.x;
y = originalPosition.y;
}
}
}
Within it i call the other class;
import Kitchen
public class DragFood extends MovieClip
{
protected var originalPosition:Point;
var myKitchen:Kitchen
The code for the kitchen class is;
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class Kitchen extends MovieClip
{
// This is a function. This particular function has the same name as our class and therefore will be executed first
public function Kitchen()
{
// This is a "call" to another function that is defined later in the program.
init();
trace("Hello world");
}
public function init():void
{
// If we want an object (on the screen or otherwise) to be notified about an event we must add a listener for that event to that object.
// We also need to specify what happens everytime the event we are listening for happens.
PowerButton.addEventListener(MouseEvent.CLICK, handleButtonClicks);
}
//This function is called when the oven on button recieves a click.
public function handleButtonClicks(event:MouseEvent):void
{
OvenOn.visible = true;
trace("the oven is being switched on");
}
}
}
The issue i keep getting is that OvenOn and PowerButton are giving me a undefined access issue and im not sure how to fix it. I have found posts on similar subjects like - Access of Undefined property? Actionscript 3
but im not quite sure how to apply it to my issue if anyone could offer any help that would be great.
When you're programming on the timeline, code is referencing the local namespace, and objects you make there (movieclips, textfields, etc.) are automatically instantiated in that namespace so that you can simply call OvenOn.visible = true. However, for each class, their local namespace is whatever is inside the class, so unless you actually created a property on your class called OvenOn, it will most definitely give you Access of Undefined Property errors.
Think of each class as its own island. For them to touch eachother, they need some sort of connection. That connection can be made once the parent instantiates the class in its own namespace. For example...
var foo:String = "Hello!";
var bar:MyClass = new MyClass();
// At this point, whatever code runs inside of MyClass has no concept of foo, or how to access it.
addChild(bar);
// Now that we've added it to the stage, the bar has some properties that have automatically been populated such as "root", "parent", or "stage".
foo.someProperty = "World";
// Since this namespace has a variable pointing to the instance, we can change properties on that class.
Now that we've instantiated MyClass on the stage, we can reference parent properties the class didn't know about. Mind you, this is not necessarily best practice.
package
public class MyClass extends MovieClip {
var someProperty:String = "cheese";
public function MyClass() {
trace(parent.foo) // this will fail
addEventListener(Event.ADDED_TO_STAGE, test);
}
public function test(e:Event):void {
trace(this["parent"].foo); // this will succeed
}
}
}
If you absolutely must change something that is not part of your Kitchen class, pass either the parent of OvenOn or that object specifically as a property of Kitchen. You could do this a couple ways.
with the Constructor...
var something:*;
public function MyClass(someObject:*) {
something = someObject;
}
public function test():void {
something.visible = false;
}
...or by Assigning the Property...
var bar:MyClass = new MyClass();
bar.something = OvenOn;
bar.test(); // will turn off the OvenOn now that 'something' is pointing to it.

AS3 - Error 1119 - Does not detect my static class altogether

Context: I began learning AS3 a week ago. All my files are in the same folder, and the path is set to . (by default anyway), so all classes should logically detect each other. But as it turns out, I have a class with a lot of public static var, and every time I call these in my other class, I get Error 1119
Access of possibly undefined property isKeyJump through a reference with static type Function.
The class with static variables is called Cont for 'Control'; it's basically meant to check which keys are pressed, just pressed, or pressed twice rapidly. I made the class to organize the code, essentially.
I declare all my variables like this:
public static var isKeyRight:Boolean = false;
And if that wasn't sufficiently explicit, I even wrote this in the constructor (I was tired):
public function Cont()
{
Cont.isKeyRight = false;
... }
But that didn't solve the issue at all. It appears the problem is independent from the class itself; it's just that my other class does not detect Cont.
I tried import Cont; but that also didn't change a thing. My 44 lines of Error 1119 look like this:
if (standing && Cont.isKeyJump) vacc = _jumpAcc;
I even made sure to instantiate the instance of Cont before that of my other class, to make sure that the definitions were at least there. But that would probably make an error after compilation if that was the issue, not during.
The bulk:
Other Class: (The one with 44 errors)
package {
import flash.display.MovieClip;
import flash.events.Event;
public class PersonnagePrincipal extends Physical {
//INITIALISATION
...
//CONSTRUCTOR
public function PersonnagePrincipal(life:Number = 100, focus:Number = 100, lifeMax:Number = 100, focusMax:Number = 100)
{
super();
...
}
// GET & SET
public function set life(life:Number):void { _life = (life > lifeMax) ? lifeMax : life; }
...
// UPDATE
override public function update(event:Event)
{
move_physical();
if (standing && Cont.isKeyJump) vacc = _jumpAcc;
...
And Cont:
package {
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.display.MovieClip;
import flash.utils.*;
public class Cont extends MovieClip
{
// Key codes
public static var isKeyRight:Boolean;
public static var isKeyJump:Boolean;
...
//CONSTRUCTOR
public function Cont()
{
Cont.isKeyRight = false;
Cont.isKeyJump = false;
...
if (stage) { init(); }
else { this.addEventListener(Event.ADDED_TO_STAGE, init); }
}
//POST-CONSTRUCTOR
private function init(e:Event=null)
{
this.removeEventListener(Event.ADDED_TO_STAGE, init);
...
}
EDIT: Well, taking all the code from Cont and into PersonnagePrincipal does solve the synthax errors (given that I get rid of the Cont.) ... But now my code is a lot less sexy and flexible.
EDIT 2: I made the class PersonnagePrincipal empty, and it worked. Stranger still, when I put the line public var control:Cont = new Control in Main, it works, while it generates a compile time error in PersonnagePrincipal. What?

AS 3.0: Calling a method, which is defined in another class, from Main class gives Error 1120

I have two classes. The Main class calls a function, which is defined in a Second class. I'm getting the following error:
Error 1120: Access of undefined property myFunction
Basically, I am creating buttons in the Main class that will add a corresponding Child to an Object in the Second class (if you click one button, child x1 will be added, if you click another button, child x2 will be added, and so forth).
Here's the relevant code for the Main.as file:
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip {
private var x1:X1 = new X1();
private var x2:X2 = new X2();
public function Main():void {
addPlayers();
}
public function addPlayers():void {
addChild(x1);
addChild(x2);
x1.x=325;
x1.y=5;
x2.x=366;
x2.y=5;
x1.label = "dog";
x2.label = "cat";
x1.addEventListener(MouseEvent.CLICK, selectPlayer);
x2.addEventListener(MouseEvent.CLICK, selectPlayer);
}
}
}
The Second.as file code is:
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.MouseEvent;
public class Second extends MovieClip
{
public var myVar:MyVar = new MyVar();
public function Second():void
{
addChild(myVar);
}
private var mc_x1:Mc_x1 = new Mc_x1();
private var mc_x2:Mc_x2 = new Mc_x2();
public function selectPlayer(event:MouseEvent):void
{
if (Game(this.parent).turn == 0) {
myVar.addChild(mc_x1);
} else {
switch (event.currentTarget.label) {
case "dog":
myVar.addChild(mc_x1);
break;
case "cat":
myVar.addChild(mc_x2);
break;
default:
myVar.addChild(mc_x1);
}
}
}
}
}
i've tried defining a new variable as a public static var and that hasn't worked. i've also tried to import the Second class in the Main class and that didn't work either. any thoughts?
thank you!
If I'm understanding what your code says, you can't do what your doing. Even though you are listening to events on X1 and X2, you are listening to them FROM main. In other words, main is attempting to handle the event, and it's not finding the function you specified (selectPlayer). If you want all event handling to happen in main, then main will have to call into X1 and X2 when it receives an event.
I agree with ThatSteveGuy , in Main you are calling a function that doesn't exist, namely selectPlayer(). Following your code the first thing you should do is add a selectPlayer() function in Main.
Then you would need to add an instance of the Second class in Main in order for the following to work
private function selectPlayer(event:MouseEvent):void
{
second.selectPlayer(event);
}
Now it's a bit difficult to advise you any further because this way of doing things looks a bit convoluted but then again I would need to see the big picture. This is just an explanation about why your code doesn't work. Also, in the Second class , selectPlayer may throw an error because Game(this.parent ) will return a null value so you won't be able to access the turn property...
Is there a good reason why you need to add the two buttons in Main as opposed to adding them in Second?
try this
public function Second():void
{
this.addEventListener(MouseEvent.CLICK, selectPlayer);
addChild(myVar);
}
(and don't forget to remove x1.addEventListener, x2.addEventListener from main)

custom AS3 Loader class that uses a custom LoaderInfo class?

This is a question specifically about creating a custom Loader class as a followup to How do I modify existing AS3 events so that I can pass data?. If this wasn't the right way to go about this, let me know.
I have a custom Loader class and a custom LoaderInfo class. What I can't figure out is how to have the Loader class use the custom LoaderInfo class as it's contentLoaderInfo property.
package com.display {
import flash.display.Loader;
import com.display.CustomLoaderInfo;
public class CustomLoader extends Loader {
public var customData:*;
public function CustomLoader(passedData: *= null) {
customData = passedData;
}
}
}
^ Have to do something in there to make it have the new CustomLoaderInfo
package com.display {
import flash.display.LoaderInfo;
import flash.events.Event;
import com.events.CustomEvent;
public class CustomLoaderInfo extends LoaderInfo {
public var customData:*;
public function CustomLoaderInfo(passedData: *= null) {
customData = passedData;
}
override public function dispatchEvent(event:Event):Boolean {
var customEvent:CustomEvent = new CustomEvent(event.type, customData, event.bubbles, event.cancelable);
return super.dispatchEvent(customEvent);
}
}
}
^ That might work, but since I can't get CustomLoader to use it, I don't know yet.
I don't know how it fits into what you're doing, but you could not bother making an extended LoaderInfo at all. Loader.contentLoaderInfo has a property called loader that will return the Loader (or in this case CustomLoader) that was used. In theory you can just do this with the CustomLoader class that you have:
var loader: CustomLoader = new CustomLoader("Extra Data");
loader.load(new URLRequest("file.swf"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete);
function loaderComplete(event: Event) : void
{
var customData:* = (event.target.loader as CustomLoader).customData;
trace(customData); // Extra Data
}
You would have to override the function where the loaderinfo instance is created, and that might be in a private function. In the new function you could then instanciate your custom loaderInfo class instead, but you would also have to do anything else that the overwritten method does. You might run into some security sandbox problems with loadinfo as well. Overwriting a function like this is usually only posible when the function written with this in mind.
Alternatively you could use the prototype chain (read here) to change the loaderInfo class at runtime. But I wouldn't recommend it. It's not good practice in my opinion.
If you get this to work you still have the problem that your custom event will not work with any event that has properties not inheritet from the Event class (like the ProgressEvent that has progress related properties).
I would say you properly should look for another solution.
In the question you link to you talk about sending movieclip with your event. Have you thought about reaching the other way? When you recieve the event, you get a reference to the object that dispatched it (Event.target). Can you not use that reference to get the movieclip?
Perhaps you could explain your problem in more detail (maybe in a new question so you still keep this open), I am sure there is a better / easier way to solve it.
I needed something like this because I wanted to carry an index with the info ... ie - have something like event.target.index available after an event is triggered .. anyway i designed a class that contained the loader and the loader info... heres the class
public class LoaderBox extends Sprite {
public static var PROGRESS:String = "progress"
public static var COMPLETE:String = "complete"
public var id:int
public var index:int
public var loader:Loader
public var info:LoaderInfo
public var isOpen:Boolean
//
public var percent:Number = -1
public function load(path:String,idx:int=-1,nm:String=null){
loader = new Loader()
if (nm != null){
name = nm
}
index = idx
var req:URLRequest = new URLRequest(path)
info = loader.contentLoaderInfo
info.addEventListener(Event.COMPLETE,complete)
info.addEventListener(ProgressEvent.PROGRESS,progress)
isOpen = true
loader.load(req)
}
private function complete(e:Event):void{
isOpen = false
dispatchEvent(new Event(LoaderBox.COMPLETE))
}
private function progress(e:ProgressEvent):void{
if (e.target.bytesTotal>0){
percent = Math.floor(e.target.bytesLoaded/e.target.bytesTotal * 100)
}
dispatchEvent(new Event(LoaderBox.PROGRESS))
}
}
A potential issue with the flagged answer: if contentLoaderInfo spits out a IOError, you can't access the .loader property to access your custom loader class.
What I did is the following:
* in my custom loader class, create the following method:
public function requestError(event:Event):void {
dispatchEvent(event);
}
when adding a listener to contentLoaderInfo for the IOerror, point to the custom loader class's method:
_loaderCls.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, _loaderCls.requestError);
Then, add the same listener to your loader class and make it call any method you need. At that point, the event.target would be that of your custom loader class and you can add any extra info you need to that class:
_loaderCls.addEventListener(IOErrorEvent.IO_ERROR, requestError);
or you can do a better thing to pass data into the Loader class:
package com.display
{
import flash.display.Loader;
public class Loader extends flash.display.Loader
{
private var _obj:Object;
public function Loader():void
{
super();
}
public function get obj():Object
{
return _obj;
}
public function set obj(o:Object):void
{
_obj = o;
}
}
}