Flash pointers for a Flex guy?
September 19, 2010 2:54 PM Subscribe
Flash pointers for a Flex guy?
I'm interviewing for a job that will involve Actionscript 3 development in Flash. AS3 is no problem, I've done Flex for three years or so. And I was doing Flash as far back as Flash 4.
I don't anticipate any problems actually doing the job; I expect I could pick it up within the first two hours. What I need help with is navigating any "gotcha" questions I might get hit with in the interview, about how modern Flash/AS3 development works.
I'm not actually sure what modern-day Flash projects look like. Is there still one line of AS code on the timeline, that instantiates the first class or movie clip? What does a "top level" clip or class look like? (In Flex you would start with a basic MXML layout and add objects via AS from there; so looking for equivalent to that.) How are objects typically added to the stage? That kind of basic stuff is what I need to know, so I don't sound stupid. It might also help to know how Unit Testing is typically done. Oh and does Flash have a good built-in AS editor by now? Or do people typically use Eclipse or something?
I've googled but haven't found a tutorial that actually covers this. Anything you can link me to would be greatly helpful, or if you could just describe the process to me that would be awesome.
thanks!
I'm interviewing for a job that will involve Actionscript 3 development in Flash. AS3 is no problem, I've done Flex for three years or so. And I was doing Flash as far back as Flash 4.
I don't anticipate any problems actually doing the job; I expect I could pick it up within the first two hours. What I need help with is navigating any "gotcha" questions I might get hit with in the interview, about how modern Flash/AS3 development works.
I'm not actually sure what modern-day Flash projects look like. Is there still one line of AS code on the timeline, that instantiates the first class or movie clip? What does a "top level" clip or class look like? (In Flex you would start with a basic MXML layout and add objects via AS from there; so looking for equivalent to that.) How are objects typically added to the stage? That kind of basic stuff is what I need to know, so I don't sound stupid. It might also help to know how Unit Testing is typically done. Oh and does Flash have a good built-in AS editor by now? Or do people typically use Eclipse or something?
I've googled but haven't found a tutorial that actually covers this. Anything you can link me to would be greatly helpful, or if you could just describe the process to me that would be awesome.
thanks!
Response by poster: That is useful, thanks! I used Flex Builder for years and years, and that is built on Eclipse, but I never knew there was a Flash Builder too!
posted by drjimmy11 at 4:08 PM on September 19, 2010
posted by drjimmy11 at 4:08 PM on September 19, 2010
Response by poster: (actually wikipedia tells me Flash Builder *is* the newest version of Flex Builder. So I already know it and didn't know it!)
posted by drjimmy11 at 4:12 PM on September 19, 2010
posted by drjimmy11 at 4:12 PM on September 19, 2010
Best answer: Yes, Flash Builder is the new name for the Flex IDE.
With Flash CSWhatever, you can code on the timeline (you can insert code into a frame on the timeline, and that code will run when the playhead reaches the specific frame), but it's not generally considered a smart way to work. Still, you should know that it's possible. Sometimes people put the code for the preloader in the first frame and the rest of the code in the second frame, e.g.
if (percentLoaded == precentTotal) gotoAndStop(2);
Pros don't do this. They put their code in a Document class. But, again, you should be aware that timeline code is a possibility.
If you click on the stage and look in the Properties panel, you'll see form field where you can enter the name of your document class. This is a much better way to work.
A typical document class looks like this:
I try to keep my Document class as succinct as possible, generally using composition to pass control to other classes (generally using some kind of MVC pattern).
As you probably know, Flash CSWhatever files have a .fla suffix. I generally save them in the same directory as my Document.as class. Since they're in the same folder, I only have to enter Document (without the .as suffix) in that form field (in the Properties panel). I then put all other code in standard packages:
myApp.fla
Document.as
- com [folder/package]
Document.as will reference classes in the com package. Then, to start the whole ball rolling, I'll open myApp.fla and press Command+Return (PC: Control+Enter) to compile everything.
An example of Document.as referencing things in the com package might be as follows:
[In Document.as]
var view : View = new View( this );
[In View.as]
public View( container : Spirte )
{
var circle : Shape = .... code to draw a circle ...
container.addChild( circle );
}
Also note that CSWhatever files have a Library in which you can store fonts and graphics, in the form of Movieclips. For instance, you can draw a rectangle on the stage using Flash's vector drawing tools. Then you can select it and choose Modify > Convert to Symbol, naming it MyRect
If you right-click on the Symbol in the Library and choose properties, you can then check the Export for Actionscript and Load on First Frame options. (I think I got the name of that second option slightly wrong, but it's something like "Load on First Frame"). Once you do that, the graphic will be associated with a Class called MyRect, even though you didn't actually create that class. (It's created for you -- virtually -- without any MyRect.as file actually existing). Now, in the Document.as file, you can type var myRect : MyRect = new MyRect; addChild(myRect); and you should see your rectangle appear on the Stage when you compile.
In Flash CSWhatever, if you choose File > Publish Settings, you'll see various options for outputting the SWF, including options for Flash to auto-generate an HTML wrapper file.
posted by grumblebee at 8:32 PM on September 19, 2010 [1 favorite]
With Flash CSWhatever, you can code on the timeline (you can insert code into a frame on the timeline, and that code will run when the playhead reaches the specific frame), but it's not generally considered a smart way to work. Still, you should know that it's possible. Sometimes people put the code for the preloader in the first frame and the rest of the code in the second frame, e.g.
if (percentLoaded == precentTotal) gotoAndStop(2);
Pros don't do this. They put their code in a Document class. But, again, you should be aware that timeline code is a possibility.
If you click on the stage and look in the Properties panel, you'll see form field where you can enter the name of your document class. This is a much better way to work.
A typical document class looks like this:
package { import flash.display.Sprite; public class Document extends Sprite { public function Document() { init(); } private function init() { ... etc .... } } }Note that a Document class must extent Sprite or Movieclip. I've never found a reason to choose Movieclip, so I choose Sprite, because it's a simpler class with less overhead.
I try to keep my Document class as succinct as possible, generally using composition to pass control to other classes (generally using some kind of MVC pattern).
As you probably know, Flash CSWhatever files have a .fla suffix. I generally save them in the same directory as my Document.as class. Since they're in the same folder, I only have to enter Document (without the .as suffix) in that form field (in the Properties panel). I then put all other code in standard packages:
myApp.fla
Document.as
- com [folder/package]
Document.as will reference classes in the com package. Then, to start the whole ball rolling, I'll open myApp.fla and press Command+Return (PC: Control+Enter) to compile everything.
An example of Document.as referencing things in the com package might be as follows:
package { import flash.display.Sprite; import com.mysite.ui.MyCustomButtonClass; public class Document extends Sprite { public function Document() { init(); } private function init() { var button : MyCustomButtonClass = new MyCustomButtonClass("OKAY"); addChild( button); } } }Note that you can use addChild( ... ) in the Document class, but other classes won't understand what this means, unless the Document class sends them a reference to "this," e.g.
[In Document.as]
var view : View = new View( this );
[In View.as]
public View( container : Spirte )
{
var circle : Shape = .... code to draw a circle ...
container.addChild( circle );
}
Also note that CSWhatever files have a Library in which you can store fonts and graphics, in the form of Movieclips. For instance, you can draw a rectangle on the stage using Flash's vector drawing tools. Then you can select it and choose Modify > Convert to Symbol, naming it MyRect
If you right-click on the Symbol in the Library and choose properties, you can then check the Export for Actionscript and Load on First Frame options. (I think I got the name of that second option slightly wrong, but it's something like "Load on First Frame"). Once you do that, the graphic will be associated with a Class called MyRect, even though you didn't actually create that class. (It's created for you -- virtually -- without any MyRect.as file actually existing). Now, in the Document.as file, you can type var myRect : MyRect = new MyRect; addChild(myRect); and you should see your rectangle appear on the Stage when you compile.
In Flash CSWhatever, if you choose File > Publish Settings, you'll see various options for outputting the SWF, including options for Flash to auto-generate an HTML wrapper file.
posted by grumblebee at 8:32 PM on September 19, 2010 [1 favorite]
Response by poster: Thanks, grumblebee! That's pretty much exactly what I needed, very thorough!
posted by drjimmy11 at 8:49 PM on September 19, 2010
posted by drjimmy11 at 8:49 PM on September 19, 2010
A huge gotcha: if you create an SWF from an FLA with a document class, then put code on the timeline, what you've essentially done is created a subclass of the document class. Now, if you load that SWF into another, and attempt to cast it to the document class (from DisplayObject, which is Loader.content's type), your timeline code isn't going to work. For example, if you have a stop() call on the timeline, it'll keep right on going. I mean, it's bad form to do that anyway, but the reason why it doesn't work isn't immediately obvious. The solution is to have the document class implement an interface and use that when you cast.
That reminds me: you already know AS3, but maybe you haven't used the Loader object much... You might be tempted to add your listeners directly to a Loader instance. Don't. Add them to Loader.contentLoaderInfo.
posted by klanawa at 8:52 PM on September 19, 2010
That reminds me: you already know AS3, but maybe you haven't used the Loader object much... You might be tempted to add your listeners directly to a Loader instance. Don't. Add them to Loader.contentLoaderInfo.
posted by klanawa at 8:52 PM on September 19, 2010
drjimmy11, it just occurred to me that in your shoes, I would pick up any basic book on the NON-programming aspects of Flash CSx and read it. Just get "Flash for Dummies" or whatever. You'll be able to learn what you need to know in a couple of hours, because Flash really isn't a very complex application. (It's not like Photoshop or Maya.)
I know you're chiefly interested in how programming in Flash is different from programming in Flex, but the non-programming aspects (e.g. the Timeline) bump into the programming aspects. Even if you never touch the Timeline, you will probably get assets from other people who have used it. And you should know how to deal with those assets. At least, if you were working for me, I'd expect you to be able to do that.
Also, CSx comes with a set of UI components, similar to the ones that come with Flex, e.g. scrollbars, buttons, etc. Note that they are SIMILAR to the Flex ones but NOT identical. You should read the docs and understand their APIs, how to skin them, etc.
One more thing: writing code on the Timeline is actually REALLY useful. I NEVER do it for production code, because it's a really bad practice, but it's an amazing way to test little things out -- it's almost like working with an interpreter. Say, for instance, that I can't remember how to draw a line. I can type this and try it out:
graphics.lineStyle(1, 0xFF0000);
graphics.lineTo(400, 100);
I can then just press Command+Return (PC: Control+Enter) and see if it works. I don't need to create a class. I find this so useful, that I keep Flash running on another monitor, even when I'm working in Flex.
But here's the gotcha: for this to work, my code snippet MUST be in Frame One of the Timeline. In Flash, code can go anywhere, and that creates all kinds of problems. For instance, let's say I have a movieclip on the stage and it's selected (e.g. I clicked on it earlier, maybe to move it up a little), and then, with the movieclip selected, I typed some code in Flash's code editor. Because the movieclip is selected, my code WON'T go into Frame One. It will become part of the movieclip.
And it won't work, because only Actionscript 1.0 (YUCK) can work as part of a movieclip. Actionscript 2.0 and 3.0 must either be in the Timeline or in external files. But because Flash still supports 1.0, it has to allow you to put code onto movieclips and buttons. When your 3.0 code doesn't work, it's hard to understand why. You may not find any bugs in it. It's probably not working because you accidentally clicked on some object on the stage before typing it.
So if you're typing code in Flash, make sure you've selected Frame One before typing it. (After clicking in that frame, you can click the little thumbtack icon at the bottom of the code editor. That will force all subsequent code to go into frame one, even if you click a movieclip.) Also, make sure that at the bottom of the Editor, you see something like "Layer 1: 1" That is indicating that any code you type is going to be associated (e.g. will run as part of) frame one of layer one.
posted by grumblebee at 7:11 AM on September 20, 2010
I know you're chiefly interested in how programming in Flash is different from programming in Flex, but the non-programming aspects (e.g. the Timeline) bump into the programming aspects. Even if you never touch the Timeline, you will probably get assets from other people who have used it. And you should know how to deal with those assets. At least, if you were working for me, I'd expect you to be able to do that.
Also, CSx comes with a set of UI components, similar to the ones that come with Flex, e.g. scrollbars, buttons, etc. Note that they are SIMILAR to the Flex ones but NOT identical. You should read the docs and understand their APIs, how to skin them, etc.
One more thing: writing code on the Timeline is actually REALLY useful. I NEVER do it for production code, because it's a really bad practice, but it's an amazing way to test little things out -- it's almost like working with an interpreter. Say, for instance, that I can't remember how to draw a line. I can type this and try it out:
graphics.lineStyle(1, 0xFF0000);
graphics.lineTo(400, 100);
I can then just press Command+Return (PC: Control+Enter) and see if it works. I don't need to create a class. I find this so useful, that I keep Flash running on another monitor, even when I'm working in Flex.
But here's the gotcha: for this to work, my code snippet MUST be in Frame One of the Timeline. In Flash, code can go anywhere, and that creates all kinds of problems. For instance, let's say I have a movieclip on the stage and it's selected (e.g. I clicked on it earlier, maybe to move it up a little), and then, with the movieclip selected, I typed some code in Flash's code editor. Because the movieclip is selected, my code WON'T go into Frame One. It will become part of the movieclip.
And it won't work, because only Actionscript 1.0 (YUCK) can work as part of a movieclip. Actionscript 2.0 and 3.0 must either be in the Timeline or in external files. But because Flash still supports 1.0, it has to allow you to put code onto movieclips and buttons. When your 3.0 code doesn't work, it's hard to understand why. You may not find any bugs in it. It's probably not working because you accidentally clicked on some object on the stage before typing it.
So if you're typing code in Flash, make sure you've selected Frame One before typing it. (After clicking in that frame, you can click the little thumbtack icon at the bottom of the code editor. That will force all subsequent code to go into frame one, even if you click a movieclip.) Also, make sure that at the bottom of the Editor, you see something like "Layer 1: 1" That is indicating that any code you type is going to be associated (e.g. will run as part of) frame one of layer one.
posted by grumblebee at 7:11 AM on September 20, 2010
It wasn't clear in my answer, but the reason my scenario doesn't work is because the document class is embedded in the loader SWF. By default, the first loaded definition of a class is the one that gets used, so the one in the loaded SWF is ignored. Since the doc class doesn't know about the timeline code, it doesn't get executed.
posted by klanawa at 12:56 PM on September 20, 2010
posted by klanawa at 12:56 PM on September 20, 2010
klanawa, as a professional Flash developer, I should know this, but I don't: what's the exact relationship between the Document Class, the SWF and the Stage? I've always gotten everything working, but I've never understood the exact mechanics, other than the fact that the Document class is the class "for" the SWF.
I understand that MovieClip is a Class, and that you can subclass it and then use your subclass as a sort of proxy, to control an asset in the Library. Since the Document class must subclass Sprite or MovieClip, I've always assumed that it's the proxy for the parent-graphical-object (the one that contains all others that get added to the display list), the SWF itself. Which is why, when you code addChild( someDisplayObject) in your Document class, someDisplayObject appears on the Stage.
But what is the Stage? It's not the same as the SWF. It seems to be its own object, and the SWF seems to have a reference to it. When, in the document class, you call addChild(), are you adding a child to the Stage or to the SWF?
This distinction almost never matters, but I did once get into a confusion over it.
One interesting thing is that you can access the Stage from any item on the display list. For instance, in a Document class...
var s1 : Sprite = new Sprite();
var s2 : Sprite = new Sprite();
var s3 : Sprite = new Sprite();
s2.addChild( s1 );
s3.addChild( s2 );
addChild( s3 );
trace( this.stage == s1.stage ); //true
Note: if you make an s4 and DON'T add it to the display list, its stage property will be null.
Anyway, one thing I NEVER do is write stage.addChild( someDisplayObject), although in theory you can do it. The docs say this:
Calling the addChild() method of a Stage object throws an exception for any caller that is not in the same security sandbox as the Stage owner (the main SWF file). To avoid this, the Stage owner can grant permission to the domain of the caller by calling the Security.allowDomain() method or the Security.allowInsecureDomain() method. For more information, see the "Security" chapter in Programming ActionScript 3.0
So I still don't really get how the stage relates to the swf relates to the Document class.
posted by grumblebee at 1:14 PM on September 20, 2010
I understand that MovieClip is a Class, and that you can subclass it and then use your subclass as a sort of proxy, to control an asset in the Library. Since the Document class must subclass Sprite or MovieClip, I've always assumed that it's the proxy for the parent-graphical-object (the one that contains all others that get added to the display list), the SWF itself. Which is why, when you code addChild( someDisplayObject) in your Document class, someDisplayObject appears on the Stage.
But what is the Stage? It's not the same as the SWF. It seems to be its own object, and the SWF seems to have a reference to it. When, in the document class, you call addChild(), are you adding a child to the Stage or to the SWF?
This distinction almost never matters, but I did once get into a confusion over it.
One interesting thing is that you can access the Stage from any item on the display list. For instance, in a Document class...
var s1 : Sprite = new Sprite();
var s2 : Sprite = new Sprite();
var s3 : Sprite = new Sprite();
s2.addChild( s1 );
s3.addChild( s2 );
addChild( s3 );
trace( this.stage == s1.stage ); //true
Note: if you make an s4 and DON'T add it to the display list, its stage property will be null.
Anyway, one thing I NEVER do is write stage.addChild( someDisplayObject), although in theory you can do it. The docs say this:
Calling the addChild() method of a Stage object throws an exception for any caller that is not in the same security sandbox as the Stage owner (the main SWF file). To avoid this, the Stage owner can grant permission to the domain of the caller by calling the Security.allowDomain() method or the Security.allowInsecureDomain() method. For more information, see the "Security" chapter in Programming ActionScript 3.0
So I still don't really get how the stage relates to the swf relates to the Document class.
posted by grumblebee at 1:14 PM on September 20, 2010
According to the docs, "The Stage class represents the main drawing area." I guess my question boils down to where the stage fits into the display hierarchy, if anywhere. In other words, is it like this?
posted by grumblebee at 1:20 PM on September 20, 2010
-SWF (linked to Document class) |--- Stage |------- other objects added using addChild( ... ) or -SWF (linked to Document class) | -- Stage | -- other objects added using addChild( ... )Neither of these seems quite right. And what's an instance where you'd ever want that write stage.addChild( ... ) as opposed to this.addChild( ... ), with this being a reference to the Document class?
posted by grumblebee at 1:20 PM on September 20, 2010
Some tests I just ran (with code on frame one):
var box : Sprite = new Sprite();
box.graphics.beginFill( 0xFF0000 );
box.graphics.drawRect( 0, 0, 100, 100 );
stage.addChild( box ); //I see the box
trace( numChildren ); //zero
----
var box : Sprite = new Sprite();
box.graphics.beginFill( 0xFF0000 );
box.graphics.drawRect( 0, 0, 100, 100 );
addChild( box ); //I see the box
trace( numChildren ); //one
var box : Sprite = new Sprite();
box.graphics.beginFill( 0xFF0000 );
box.graphics.drawRect( 0, 0, 100, 100 );
stage.addChild( box );
trace( stage.numChildren ); //two
TWO? Interesting!
----------
var box : Sprite = new Sprite();
box.graphics.beginFill( 0xFF0000 );
box.graphics.drawRect( 0, 0, 100, 100 );
stage.addChild( box );
for ( var i : int = 0; i <> trace( stage.getChildAt( i ) );
trace output:
[object MainTimeline]
[object Sprite]
Oh, WOW! I never knew that. So, it looks like...
posted by grumblebee at 1:28 PM on September 20, 2010
var box : Sprite = new Sprite();
box.graphics.beginFill( 0xFF0000 );
box.graphics.drawRect( 0, 0, 100, 100 );
stage.addChild( box ); //I see the box
trace( numChildren ); //zero
----
var box : Sprite = new Sprite();
box.graphics.beginFill( 0xFF0000 );
box.graphics.drawRect( 0, 0, 100, 100 );
addChild( box ); //I see the box
trace( numChildren ); //one
var box : Sprite = new Sprite();
box.graphics.beginFill( 0xFF0000 );
box.graphics.drawRect( 0, 0, 100, 100 );
stage.addChild( box );
trace( stage.numChildren ); //two
TWO? Interesting!
----------
var box : Sprite = new Sprite();
box.graphics.beginFill( 0xFF0000 );
box.graphics.drawRect( 0, 0, 100, 100 );
stage.addChild( box );
for ( var i : int = 0; i <> trace( stage.getChildAt( i ) );
trace output:
[object MainTimeline]
[object Sprite]
Oh, WOW! I never knew that. So, it looks like...
stage |--- SWF (e.g. Main Document Class) |--- other display objects>
posted by grumblebee at 1:28 PM on September 20, 2010
package { import flash.display.Sprite; public class Document extends Sprite { public function Document() { var box : Sprite = new Sprite(); box.graphics.beginFill( 0xFF0000 ); box.graphics.drawRect( 0, 0, 100, 100 ); stage.addChild( box ); for ( var i : int = 0; i <> trace( stage.getChildAt( i ) ); } } } >[object Document]
[object Sprite]
posted by grumblebee at 1:32 PM on September 20, 2010
Those for loops should be ...
for ( var i : int = 0; i < stage.numChildren; i++ ) trace( stage.getChildAt( i ) );
posted by grumblebee at 6:33 PM on September 20, 2010
for ( var i : int = 0; i < stage.numChildren; i++ ) trace( stage.getChildAt( i ) );
posted by grumblebee at 6:33 PM on September 20, 2010
Think of the stage as something that is integral to the player. When you run an SWF -- that is, when you run the player and add an instance of your document class to its stage -- the stage property is set to the Stage instance owned by the player, which is the root of the display list.
If you make a loadable SWF, it has no stage property until you load it into another SWF and add it to that SWF's display list. Then the stage property in both SWFs refers to the Stage instance that was instantiated when the player started.
AFAIK, you could never subclass or instantiate or subclass Stage. There is only ever one instance, and you can't really do anything with it, other than add stuff to it.
I ran into the problem I mentioned above right about when AS3 was introduced, and I hadn't fully grokked the whole display-list concept yet (even though AS3 makes a hell of a lot more sense than AS2). It was nightmare times until I figured out what I was doing wrong and then it seemed painfully obvious.
posted by klanawa at 9:26 PM on September 20, 2010
If you make a loadable SWF, it has no stage property until you load it into another SWF and add it to that SWF's display list. Then the stage property in both SWFs refers to the Stage instance that was instantiated when the player started.
AFAIK, you could never subclass or instantiate or subclass Stage. There is only ever one instance, and you can't really do anything with it, other than add stuff to it.
I ran into the problem I mentioned above right about when AS3 was introduced, and I hadn't fully grokked the whole display-list concept yet (even though AS3 makes a hell of a lot more sense than AS2). It was nightmare times until I figured out what I was doing wrong and then it seemed painfully obvious.
posted by klanawa at 9:26 PM on September 20, 2010
This: "it has no stage property" should read: "it's stage property isn't set..."
posted by klanawa at 9:27 PM on September 20, 2010
posted by klanawa at 9:27 PM on September 20, 2010
This thread is closed to new comments.
The AS editor in CS5 is improved over previous versions-- it now has at least a few of the modern features you'd expect from Eclipse and other full IDES, like hinting for your own methods and classes, and automatically inserting import statements. But if you're not using the timeline or the graphical editors at all, you might prefer to use Flash Builder, which I think is built on top of Eclipse.
posted by moonmilk at 3:52 PM on September 19, 2010 [1 favorite]