Referencing flash instance names in actionscript 3 - actionscript-3

I am trying to reference a movie clip through its instance name which I have called "mc_mycursor" inside flash.
I want to access this movie clip inside my main document class which runs the entire application. Till now I have been exporting all objects on my stage to classes and then adding them as child objects to my stage which works fine but I would like to know how to directly refer to an object inside stage in AS3 just by using its instance name.
I have declared the variable in my main doc as follows
private var mc_mycursor:MovieClip;
but when i try to do something like mc_mycursor.x = 500, it throws an error. I am new to Flash so some help would be appreciated.

You first need to instantiate it like:
mc_mycursor = new MovieClip();
addChild(mc_mycursor);
You can do this in the constructor or at least before you try to modify properties.

Related

Model-view design in Flash

I'm creating a simple game to learn Flash programming. To have a clean model/view separation, I want to create a Player class which simply holds data relevant to the user. I'm also creating a StatusView class which extends MovieClip and which coresponds to a movie clip symbol which I've created in my Flash project. Basically the StatusView will display the data of my Player class onscreen.
I'm used to doing this sort of thing using listeners, so I've found the EventDispatcher class and added one as a member of my Player class. I'd like to have my StatusView movie clip add an event listener to my Player class so that it can receive messages whenever I change the data in my Player class.
The problem is, there doesn't seem to be anywhere for me to put my Player class so that the StatusView can find it (to add the listener). Everything in the project is created directly by one of the movie clips, and the runtime seems to create these movie clips in an arbitrary order. For example, say I create a MovieClip symbol called GameView and I create the instance of the Player there, and GameView is the parent of StatusView. When StatusView is constructed, I'd like to be able to access the Player from it's parent, but at that point GameView hasn't had it's constructor code run yet. This is true even if I wait for the ADDED_TO_STAGE event.
I could put the game model code in a singleton, but this seems like a hack to me. Is there a best practices way in Flash that lets me create and access my game model independent of all the MovieClip symbol stuff?
If you want to pass the reference of the Model to the constructor of the View, but are not calling the constructor yourself (because you do not create the object via code) you are out of luck here.
You could instead simply define a method on your View to pass a reference of the Model object:
public function setModel(value:Model):void
usage:
view.setModel(player);
There's no "law" that you have to pass the Model to the constructor of the View.
You can also create a set function for convenience:
public function set model(value:Model):void
usage:
view.model = player;
I feel like I have to disagree on the Singleton. The purpose of a Singleton is to guarantee that there's only one instance of it in existence. That's it.
It is not there to pass reference around easily (because the method to get the single instance is static). This is (IMO) a bad practice.
You could make anythign static in order to pass it around "easily". But this would make a mess and nobody does that.
But suddenly, just because the singleton pattern uses a static method, a lot of people think it's a clever way to get to the reference. I beg to differ.
First of all, you could implement Player class as singleton if you need just one instance. I don't think that that looks like a hack (for example, in PureMVC framework each model is a singleton).
At second, you can create instances of Player class in some general class (manager) and send them to views.
P.S. Also, I want to note that you can extend your Player class from EventDisptacher without creating specific field "eventDispatcher" in Player class. I don't know what way is better, but this one is simpler, imho.

AS3: How to instantiate the generic 'Document Class' (MainTimeline?) of a loaded SWF?

I have "Question.swf", which was created from "Question.fla". Note that Question.fla has no Document Class associated with it. (Note that this is legacy content, and there are over 14,000 variants of "Question.swf"; changing all these is not a viable option.)
Now I have my main Flash application, which loads in Question.swf at runtime. I know that Question.swf has a "Document Class" automatically created which represents the entire "stage" of the SWF (and that it's named "MainTimeline"). I want this application to be able to instantiate multiple instances of that Question.swf Document class... how can I?
I've been working with Flash/AS3 since 2006 (I'm very familiar with loading/using external content, the ApplicationDomain, etc.), but I find that I have no idea how to do this!
Things I've tried which haven't worked include querying the relevant ApplicationDomain with hasDefinition( "Question_fla.MainTimeline" ) - this returns false - as well as running getQualifiedClassName() on my loader.content object - this just returns MovieClip.
I'm not sure how to duplicate the main content of the Loader. However, a reasonable workaround might be to load the SWF bytes once and create multiple Loaders from those bytes:
Load your SWF bytes with a URLLoader:
var urlloader : URLLoader = new URLLoader();
urlloader.load(new URLRequest("your url here"));
Once it is loaded, use the bytes to instantiate new display objects:
var loader : Loader = new Loader();
loader.loadBytes(urlloader.bytes);
Use your loaded loader's loader.content display object on the display list (or the loader itself).

How to add a MovieClip from the library to the stage programmatically?

I am wondering how to add a MovieClip from the library onto the stage programmatically.
How would I go about doing this?
Symbols within Flash may define ActionScript Linkage.
AS Linkage may be set by right-clicking a symbol from the library and selecting Properties...
Check Export for ActionScript and enter a Class name.
If you don't need to explicitly define a base class beyond the symbol type, you can enter AS Linkage directly from the Library:
This creates a class definition no different than if you had written an ActionScript class.
Create instances by instantiating new instances of your AS Linkage type:
var symbolExample:SymbolExample = new SymbolExample();
addChild(symbolExample);
You will essentially be creating a "class" for your movieclip. Do what James suggests above... But when calling it into your program you will have to execute something like this:
//instantiate your object
var movieClip:MovieClip = new MovieClip;
//add it to the stage
addChild(movieClip);
//object will default to x=0 , y=0 so you can define that as well
movieClip.x=100;
movieClip.y=100;
//and so on...
movieClip is whatever you want... but MovieClip is the name you assign the class in the properties dialog. These var/class relationships are typically case sensitive so follow this formula for anything you create in your library.
There are many different ways to call and remove your objects, and it can get simpler or more complicated depending on what you intend to do with your object. For instance, you can tell the object which layer to occupy with:
addChildAt(movieClip, 1);
this adds movieClip to layer 1 or the layer just above the bottom-most layer.
Hope this helps...
You create your movieclip via any method you want, then when it is in the library you right click and select Properties, check the box Export for Actionscript, choose a class name and export in frame 1. Then whenever you want to add it you add it as you would any other object. I'm sure someone else will have a more detailed explanation after me, this is the general idea.

Flash/AS3: How do I access <Instance Name> object from the Document class?

In Flash CS4, I can give an object in my timeline an instance name via the properties pannel. I figured this variable would be available to me in my Document class, but when I try to access it, it's null.
How can I get access to these instance from within my Document class? Also, do the objects have to be in the timeline at frame 1 in order to be available to my Document class's constructor?
The constructor is always the first thing called on an object, it is used to get the memory necessary to store all the properties for that object type. After an object is constructed then (assuming it's a display object) at some point it's added to the stage. If an instance of one of your objects is added to the stage on a frame then the main document class will have to know when that object was added to the stage to appropriately access it. You could create the instance of the object within your document class constructor then when added to stage fires on your main class you could add the instance.
Just attempted this wasn't able to reproduce the OPs initial behavior, I'm able to access the instance that is added on frame 1, posted some examples here:
http://www.shaunhusain.com/TestHandleOnInstance/TestHandleOnInstance.as
http://www.shaunhusain.com/TestHandleOnInstance/TestHandleOnInstance.swf
http://www.shaunhusain.com/TestHandleOnInstance/TestHandleOnInstance.fla

Flash crash (ends up in a restart loop) when loading an external swf

Im working with FlashDevelop and have two main projects, all pure AS3 projects.
When trying to load my second project from my main project I get all kinds of errors.
The Main class of the main project extends Sprite and the Main class in the "to-be-imported" project extends MovieClip. Looking at the loading of the swf in the debug window in FD it all seems fine:
[SWF] 'pathToSwf'\secondProject.swf - 410 626 bytes after decompression.
If i try to assign the loaded swf to a newly created MovieClip I get a coercion failiure:
swfContent = loader.content; // =>
Type Coercion failed: cannot convert Main#46c0201 to flash.display.MovieClip.
So, typecasting the loaded content like so:
swfContent = loader.content as MovieClip;
removes that error but then I fall into the next pit as I try to call addChild:
Error #2007: Parameter child must be non-null.
Trying to get around the issue I tried to add the loader directly into the container where I want to show the external swf. This is when the real interesting problems begin:
targetContainer.addChild(loader);
My main application now hang, restarting in a never ending loop. I have no idea why..
So my issue is really. How can my external swf be loaded but then again be null.
It works perfectly fine when I run the external swf by itself...
Use getQualifiedClassName and getQualifiedSuperclassName functions (and even describeType if you must) on loader.content to get its exact type information.
loader.content as MovieClip returns null because loader.content is not a MovieClip - casting with as keyword silently returns null when it fails. Is there any chance that the loaded content is an AS2 movie clip instead of AS3 movie clip? In that case getQualifiedClassName will return "AVM1Movie".
The latter issues is weird, but first try changing the type of swfContent to Sprite. A main class does not always extend MovieClip, and judging from the error message it indeed doesn't in this case.
Your swfContent will be null, if it cannot be casted to MovieClip. That is how the as operator is supposed to work when type coercion fails.
Modify your assignment operation like this:
var swfContent :MovieClip = MovieClip(loader.content);
You might want to encompass the assignment in a try...catch block, as an error will be thrown in case of failure, instead of swfContent being set null, as with as.
So the problem was that the main class of my loaded swf had the same name as the swf I was loading from. This led to that when flash tries to execute the loaded swf it actually calls the parent MAIN class which results in the looping behaviour.
To avoid this DHuntrods suggested to change the application domain which solved the issue.
loader = new Loader();
var AD:ApplicationDomain = new ApplicationDomain( null );
var context:LoaderContext = new LoaderContext( false, AD );
loader.load(new URLRequest(path), context);