Share/Save/Bookmark Subscribe

Thursday, April 29, 2010

Flash development workflow for traditional dev teams, Part 1

I'm a fairly old-school developer, and probably a little on the obsessive compulsive side, so the (perceived) messiness of flash development always frightened me a little. Flash development (as I've always understood it) has some nasty elements that go against everything I consider 'proper' development practices:

  • Large amounts of code are essentially stored inside what should be art resources.
  • A large chunk of the project is tied up in a single file that can only have binary differences applied to it (and hence can't be safely worked on by multiple team members without an exclusive svn lock) .
  • Either programming seems largely reactionary to what the artist adds, or the artists are restricted to some obscure naming convention imposed on them by the programmers.
  • There's no clear boundary between user interface and logic layers, with the mix of layers, frames and code potentially anywhere, finding the bit of code that actually does something a pain and unit testing almost impossible.
  • There's no clear documentation system.
  • Code editing in Flash is archaic. No autoformatting, limited lookup and completion, basically it's like coding in Notepad-but notepad's text area doesn't lose focus every time you swap away to another app and back again.
Of course Flash development has some compelling properties that make writing it off completely just plain silly:
  • It gives artists incredible creative power, they can do all sorts of cool stuff without a programmer needing to be involved or writing frameworks and tools for animation, effects, etc.
  • It allows artists to see what the end product will look like at any stage-essentially providing them with unit testing that programmers take for granted.
  • It has a HUGE install base, across just about every platform and does a solid job of delivering on the "write once, run anywhere" promise (especially if you stick to older standards that are compatible with many mobile devices).
  • Chances are, there's no big download required for the user, they are very likely to already have flash installed.
  • There are tons of programmers and artists out there familiar with the toolset, so hiring for teams or finding contractors is made a lot easier.
So when a new project came along that needed to be implemented in Flash and I couldn't find any resources on Flash project management that suited my needs, it was an opportunity to set up the kind of workflow that both programmers and artists on the team could be comfortable with. What follows is a description of the results.
For reference, these were my limitations:
  • Use Flash Lite 2.0 and Actionscript 2.0 (for the most part this should all apply to other versions as well though)
  • Use Adobe Creative Suite 4 (solutions that removed the actual flash tools from the workflow kind of defeated the point of having artist friendly tools)
I ended up settling on FlashDevelop as an IDE as it does a good job of implementing the code editing features missing from Flash itself.
Setting up the project
In FlashDevelop, create a new ActionScript 2 Flash IDE project as shown in Screenshot 1.
You can obviously change the settings to your liking.
In the Project view, create the folders (right click the project icon, Add->New Folder) that will house your source and output files. The FlashDevelop wiki suggests a convention of src to hold your source (in this case meaning .fla and .as files and any resources not intended for distribution) and bin for your distribution binaries. It's also worth creating your code package folders at this stage (as in Java style packages, or C++ namespaces). See Screenshot 2 for what the result should look like.
By default FlashDevelop uses your project root as the classpath, so this needs to be updated for the new layout. Open the Project Properties (right click the project icon in the Project view, select Properties...) and in the Classpaths tab, click Add Classpath and select your newly created src folder. After clicking Ok in the file dialog, the result should look like Screenshot 3.
The main flash file
Now open up Flash, create a new Flash file using whatever settings are appropriate for your project, and save it in your new src folder (directly in src, not in a subfolder). You'll want to configure the file to be exported to your bin folder. To do this open up the publish settings dialog (File->Publish Settings) and on the Formats tab, change both the Flash and HTML File values to include "..\bin\" as in Screenshot 4.
If you now compile and execute the flash file (Ctrl+Enter), you'll see the resulting .swf is created in your bin folder.
Note: for source control purposes, you can add a rule to ignore all .swf files in the bin folder, to avoid bloating your repository or having conflicts due to binary differences.
At this point it's a good idea to set up layers for your (two lines of) Actionscript code, frame labels and scene objects; and to set up the top level state frames for your application. Don't worry if this sounds like the 'messy' flash you've heard of, it's just to keep things well organized.
First add two new layers to the timeline (probably at the bottom of the Flash window, Right Click on the name of the automatically added Layer 1 and select Insert Layer). Now rename the layers, from top to bottom, to Actions, Labels and Objects respectively. To rename a layer, just double-click on it's existing name. Your timeline should now look something like Screenshot 5.
Now add the labels for your states. Open up the Properties view (most likely one of the tabs near the top-right of your Flash window). In the timeline, click on the first frame in the Labels layer and set it's Name in the Properties view to Init. You should notice a little red flag now in the timeline indicating this is a named frame. Now add another frame by right-clicking in frame 10 on the Labels layer and selecting Insert KeyFrame. Name the frame (in the Properties view) Menu. Add another keyframe at frame 20, and call it Level. Finally add another keyframe at frame 30, don't worry about naming it, it's sole purpose is to ensure your previous label is visible. Your timeline should now look like Screenshot 6.
You can think of these named frames as the main states your application will be in. Init will be the the frame the application starts in (and where we'll do our ActionScript magic), Menu is where the application will be advanced to once initialization is complete to allow the user to interact with a menu, and Level will be the actual game level. At a later stage you can easily add to these states.
The application class
Note: This is a workaround for there not being a document class in Actionscript 2. In Actionscript 3 this can apparently be done in a far less hacky way, by specifying an application class in the IDE.
Moving back to FlashDevelop, create a new class in your package (right-click the package, Add->New Class) called App, and set it's Base Class to MovieClip as illustrated in Screenshot 7.
A class template will be generated for you that includes a constructor and not much else:
 * ...
 * @author Matt Benic
class us.benic.matt.App extends MovieClip
        public function App()
Note: The comment block at the top of the file with the @author tag in it is Javadoc commenting. FlashDevelop has full support for Javadoc, a well established system typically used to document Java libraries. The doc generator can be found under Tools->Flash Tools->Documentation Generator..
 At this point if you click Check Syntax button on the toolbar your code should compile successfully. If it doesn't, make sure you set the project classpath as described earlier.
There should only ever be one instance of this class in existence, and it'll be useful to be able to access it from other classes in the app (no more dodgy calls to a named root document), so add very basic singleton access:
* The main MovieClip instance.
private static var instance:App;

* Singleton accessor.
public static function getInstance():App
return instance;
Because this class is a MovieClip subclass, Flash actually allows the main document's prototype class to be replaced with it at runtime. To take advantage of this, add a main() function that will achieve this:
* Application entry point.
public static function main(movieClip:MovieClip):Void
movieClip.__proto__ = App.prototype;
Because the actual MovieClip instance has already been instantiated (with the default MovieClip constructor) it's necessary to do the additional initialization in a standard method. There are tricks to force the subclassed constructor to run, but that seems a little too hacky for my liking. Here's the init method:
* Initialize the instance.
private function init():Void
// Set static instance
instance = this;

// Register frame event handler
this.onEnterFrame = this.onEnterFrameHandler;

// Jump to the Menu named frame
In addition to setting the singleton pointer, the init method sets the document's onEnterFrame event handler and progresses the MovieClip to the Menu named frame created earlier. The onEnterFrame event fires every frame and becomes your update loop (there is no explicit render loop). For now just provide a simple implementation for the function that outputs the current frame:
* Frame event handler.
public function onEnterFrameHandler():Void
trace("Frame: " + instance._currentframe);
For a complete listing of the App class thus far, click here.
Registering the application class 
Now to actually get the App class registered and updating. Go back to Flash, click on the first frame in the Actions layer and open Flash's Actionscript editor (F9 or Window->Actions). Import your package, and call the App class's (static) main function as follows:
import us.benic.matt.*;
Now if you run the Flash file, you should see "Frame: 10" repeatedly output to the Output view in Flash. Our custom handler has replaced the document's prototype with itself, grabbed a reference to it, advanced to the Menu frame and is now updating on each render. Note that despite the call to gotoAndStop in the init method, our object is still receiving updates. This is because while the timeline is stopped at that frame, the document itself is still rendering at a steady framerate, and re-entering the same frame. Any objects in this frame, however, will continue animating within their own timeline.
For the full project so far, click here. In the next post on this subject I'll go into how you can cleanly import MovieClips from additional Flash files for modular resource control, and associate them with classes in your framework, gaining easy access to their sub-objects.


Posted via email from Matt's thoughts

blog comments powered by Disqus

Copyright 2007 All Right Reserved. shine-on design by Nurudin Jauhari. and Published on Free Templates