removeChild added in an other class - actionscript-3

I've got a little problem.
I'm trying to remove a child called in an other class.
I've called "viseur" in my Engine class like that :
private var viseur:Viseur;
viseur = new Viseur(stage);
stage.addChild(viseur);
Now, in my Puzzle.as class I'd like to removeChild(viseur) when my puzzle is complete.
How do I do to do that ?
I've tried :
Engine.viseur.stage.removeChild(viseur);
But it is not working... (and either Engine.viseur.removeChild(viseur) )
Anyone know how could I do that ?
Thank you very much,

There are two issues at play here:
The call Engine.viseur.stage.removeChild(viseur); does not work because the variableviseur is private to the Engine class. If you wish for it to be accessible to other classes, you need to make it public.
However, the other issue with this is that the viseur variable is not a static variable either. So accessing it like this, Engine.viseur.stage.removeChild(viseur); is still incorrect even if you fix the variable to be public. if you wish to access it via another class, you can either 1) pass a reference of the instance of the Engine class to your other class so that it can access the viseur variable or 2) make the viseur variable a static variable, but remember if you do this, that means you can only ever have one Viseur object named viseur.

Related

Accessing variables on Document class from a child class

There is a lot of confusion online about this topic, and I am amongst the confused.
Every time I try to change a variable on the Main.as from another class it fails.
What's worse? I remember doing this in the past in as3.
public var mainVar:String = "CHANGE ME"; //on Main.as
Types of things I try:
MovieClip(root).mainVar = "changed"; //error #1009
parent.mainVar = "changed"; //error #1119
this.parent.mainVar = "changed"; //error #1119
Main..mainVar = "changed"; //error #1119
I try to call a function and get similar results using the same language.
Thanks in advance for anyone who tries to help.
There have been so many times that it seems like the best idea to store the functions in the class and have them work off the main.as vars once they are called, but I can never find a reliable way to do this, and end up adding children and setting event listeners dynamically, and only working with vars from the main.as. It's easy to do the opposite, changing a var stored on the class from main.as.
Your "problem" is that AS3 is OOP, which means that classes work separately and you need to connect them. The old "way" of doing this (using root) is absolutely wrong when dealing with bigger projects.
There are many ways to do the connection between classes. First, your Main class acts like root (if defined as base class through Properties in Flash IDE). So if you create a class that is DisplayObject and add it to the main class (using addChild();), then you will be able to do much like before:
MovieClip(parent).myFunction();
I don't recommend this, but instead more reliable solution - pass the main class to the classes that must use it:
var somethingCustom:MyClass = new MyClass(this); // inside Main.as
Then in your newly created class save this as a variable and call functions from it:
var _root:DisplayObject;
public function MyClass(root:DisplayObject) { // MyClass.as
_root = root;
_root.callPublicFunction();
}
There are many resources that can help you understanding classes (saying so because this is the normal way they should work):
How Actionscript 3 Classes Work
http://www.untoldentertainment.com/blog/2009/08/25/tutorial-understanding-classes-in-as3-part-1/

Error #2136: swf contains invalid data

public function starttank(event:MouseEvent):void
{
var Tankdrive:TankDrive = new TankDrive();
Tankdrive.tankstart();
}
It's saying that something in that function contains invalid data.
I have no idea what it is, i checked TankDrive and tankstart(); and both are correct, tankstart() is a public function...
I'm stumped...
EDIT: Error:
Error #2136: The SWF file file:///C|/Users/BigRed/Desktop/TankDrive/TankDrive.swf contains invalid data.
at mainmenu/starttank()
That's the error...
And above the starttank() function is still the same...
Ok, I looked over the files.
I'm puzzled by what you are trying to do.
Your Document class is TankDrive, and it creates an instance of mainmenu, which create ANOTHER instance of TankDrive when you click a button. Which is not what I think you want to do, or you think it's allowing you to access your document class. -- it's not. It's attempting to create a whole new instance of your game.
In short, your design is not making sense, and it's also causing a conflict with the document class resulting in that error.
The quick solution is to NOT have your EventListener & handler for the click in the mainmenu class, and then call the tankstart() method of your document class instead of attempting to create a new instance of TankDrive.
First move that listener into the document class and modify like this :
main.enterTank.addEventListener(MouseEvent.CLICK, starttank);
and then move your handler to the TankDrive class and modify as follows :
public function starttank(event:MouseEvent):void
{
tankstart();
}
This is not the only way to do this, and not really the way that I would do it. But I think that discussion is beyond the scope of this question.
If you want you can contact me at prototype.in.training#gmail.com for more details on that.
The problem is that you have an instance name that's also a class name (and the compiler has assumed that you meant to reference the latter). You probably meant to call your TankDrive variable 'tankDrive', so changing your code snippet to the following will probably help:
public function starttank(event:MouseEvent):void
{
var tankdrive:TankDrive = new TankDrive();
tankdrive.tankstart();
}
It's common and recommended to start all public variable names with a lower case letter, private variables with an underscore, and class names with a capital, though this isn't enforced by the language itself, so this kind of thing can happen.
Here are some guides on conventional variable and function naming that can help you keep track of what each of your vars and functions are supposed to do:
http://www.adobe.com/devnet/actionscript/learning/as3-fundamentals/variables.html
http://www.adobe.com/devnet/actionscript/learning/as3-fundamentals/functions.html
Good luck!

getDefinitionByName not finding a variable that exists

I am using flash.utils.getDefinitionByName in an attempt to grab an art asset. I use this function quite a bit and haven't had trouble until now. Check it:
assetName = Assets.MegaBerry; // works
assetName = getDefinitionByName("Assets.MegaBerry") as Class; // doesn't work
What the heck?? Error response for the second line is "Variable not found."
If it matters: Assets is a file in my root source directory (it has no package; Assets is the fully qualified name) and I've tried putting:
import Assets;
at the top with no luck.
For reference, in Assets.as I have:
[Embed(source = "../art/Inventory/MegaBerry.png")]
public static var MegaBerry:Class;
Your problem is that embedding the resource into the Assets class will create a static variable of type Class that belongs to that class - which is what you are referencing when you use Assets.MegaBerry: A variable(!) of type Class.
It does not, however, register the MegaBerry class to a fully qualified class name. To do this, you have to use - who would have guessed it - registerClassAlias at some point in your application:
registerClassAlias("Assets.MegaBerry", Assets.MegaBerry);
After that, it will be available everywhere else when calling getDefinitionByName.
** EDIT **
Well that's some unexpected behavior... It turns out, the class that was embedded is in fact automatically registered, but under {className}_{variableName}, instead of the notation you would expect. So using:
getDefinitionByName("Assets_MegaBerry") as Class;
should to the trick.
registerClassAlias also works, but then you need to call getClassByAliasinstead of getDefinitionByName. Sorry for the mix-up.
** END EDIT **
You can also use the Embed tag to inject the resource into a separate class file, which you can then reference as expected by using getDefinitionByName, or simply using an import:
package assets {
[Embed(source="../art/Inventory/MegaBerry.png"]
public class MegaBerry extends BitmapData {
}
}
Instead of calling
assetName = getDefinitionByName("Assets.MegaBerry") as Class;
, instead just use:
assetName = Assets["MegaBerry"];
try:
[Embed(source = "../art/Inventory/MegaBerry.png" , symbol="MegaBerry")]
public static var MegaBerry:Class;
In actionscript, objects actually have a name property that is different from the actual variable name as it shows in code.
For example, if you create a variable as follows,
var myBerry = new MegaBerry();
Then getDefinitionByName("myBerry") will return null.
Only when you set the name of the variable by writing myBerry.name = "myBerry", will getDefinitionByName("myBerry") return what you want it to. The name of the object doesn't necessarily have to be equal to the variable name in code.
In your specific case, I don't think you need to use any of that anyways. Have you tried assetName = new MegaBerry() ?
If you want to find out what the fully qualified name of you class really is, you may do the following:
trace(getQualifiedClassName(Assets.MegaBerry));
You may do that from inside Assets.as, for instance.
You can feed that string back to getDefinitionByName() and get a reference to the class.
trace(getDefinitionByName(getQualifiedClassName(SomeClass)));
// output [class SomeClass]
And remember, getDefinitionByName() only gets you references for classes that are in the same scope as the getDefinitionByName call itself. So, if you are loading external SWFs, getting class references will depend on the application domain you are using and the place, where this code executes.

How to replace an instance of a class with a cast, while all references to it remain working

Let's say I have many instances of 'Item'.
Later, I want to change some of them to 'SpecialItem' which extends 'Item'.
Can I replace the instance of Item by an Instance of SpecialItem, without having to update all existing references to the old instance of Item?
...So i'd like to do
this = this as SpecialItem
But ofcourse, you can't do that with 'this' ;)
You can only cast backwards, or 'up' the inheritance chain. Something like:
var item:Item = mySpecialItem as Item;
If you need more advanced runtime swapping abilities, think about using composition instead of inheritance, eg, referencing your items as Interfaces instances instead of Class instances.
However, as #IronBCC says, if you are just looking to swap properties, you can do so by making the property public.
No, your can't do this.
But you may use such construction:
class Link {
private var _link:*;
public get link(){}
public set link...
}
and user link.link, to get your Item, and link.link = new SpecialItem(), to set new value.

trouble accessing non-static functions from static functions in AS3

I have a class containing, among other things, a drop down menu. With the aim of saving space, and since the contents of the menu will never change, I've made a static DataProvider for the whole class that populates each instances menu. I was hoping to populate the list with actual functions like so:
tmpArr.push({label:"Details...", funct:openDetailsMenu, args:""});
and then assign tmpArr to the DataProvider. Because the DataProvider is static the function that contains that code also needs to be static, but the functions in the array are non-static. At first it didn't seem like a problem, because when the user clicks on a menu item the drop down menu can call a non-static "executeFunction(funct, args)" on its parent. However, when I try to compile, the static function setting up the DataProvider it can't find the non-static functions being passed. If the compiler would just trust me the code would work fine!
The simple solution is to just pass strings and use a switch statement to call functions based on that, but that's big, ugly, inelegant, and difficult to maintain, especially if something inherits from this class.
The simpler solution is to just make the DataProvider non-static, but I'm wondering if anyone else has a good way of dealing with this? Making the static function able to see its non-static brethren?
Thanks.
OK, the basic reason for making things static is if you want to make it independant of an instance, for example the Math functions in as3 (you call Math.min() as opposed to var math = new Math(); math.min()...) this is useful for reference, repetetive calculation, simple actions (add 10 to x value) etc.
the problem with combining static and non static functionality is that when calling a static function, there is a possibility that the class has no instance at that point, or (in this case) that there is any reference to the function that would make sense in compilation (if a seperate class called the function, how would it reference openDetailsMenu?).
what you need to do is either go through getting function by name (object"functionname" works for example), make annonymous functions in your array or alternatively add a callback method to your static function something similar to this:
public static function doAction(object:Menu, event:String){
if(event == "details") object.openDetailsMenu() ;
}
all in all you are just adding layers of complexity that isnt really going to help. if you just add a class function and get them all to do the same action it is not taking more space or effort than if you are calling to a static function. you need to think about how and why the function is going to be used in (or out of) the class.
you could just store a static reference to the instance, in this case _instance. ( Kind of like a ghetto singleton ) just be careful not to call the static method before the class has been instantiated.
/// in your constructor define a static reference handle to the instance
public function ClassName(){
_instance = this;
}
public static function doSomethingStatic(){
var varValue = ClassName._instance.someInstanceVariable;
}