Today Jason got his Actionscript 2.0 class hierarchy working, which was very exciting for the both of us. It was interesting to see how he would approach the AS2.0 environment for the first time; I gave him very minimal guidance on how to architect it. He came up with some interesting ideas regarding his multi-screen application skeleton.
Jason came up with several neat concepts by himself:
- Scenes: a collection of MovieClips, created by a SceneConstructor
- Schemes: an event manager that is associated with a particular Scene. A global EventManager class manages a set of Schemes associated with a Scene.
- Actions: a generalized set of actions, like “Go to Scene” or “Scale MovieClip”, that are invoked by a Scheme. Sort of like a command language.
Progress was going a little slow this week, so we did a code review last night. While the concepts were pretty cool, we did find a few things that were holding things up:
- Ambiguity of Terminology: Scenes / Screens / Schemes, EventManager, SceneConstructor, and Actions created a rather unwieldy mass of concepts. We were constantly forgetting the difference between a Scene and a Scheme. Obfuscating the issue even more was the relationship between classes: EventManager managed Schemes. SceneConstructor was what actually set up Events, except they were called Actions, and Actions weren’t quite working yet. Sometimes the variables would be named slightly differently…does a
stageIndexrefer to a Scene, a Screen, or a Scheme? Or is it something else? It could be simpler, and more consistent.
Object References, Everywhere: Confronted with object oriented programming for the first time, the first instinct seems to be to pass object references all over creation. A lot of code was written to propagate these object references down chains of objects…quite unwieldy.
Lack of Common Symbol Definitions: This was more of a defensive programming thing. Scenes (the collection of movieclips) used a string literal to identify what particular Scene was currently being shown. Think of this as the Active Scene. Now, event management is handled by Schemes (the collection of Handler methods that receive events fired by our GUI components). There is also the notion of an Active Scheme. Both of these active schemes and scenes (I know, it’s confusing) used a string literal to set which one was active. And they were both different. And they had to be replicated in two or three other places in
Circular Creation Dependencies: Inside the Application object are two high level objects, the Event Manager (EventManager and Scheme/Scheme subclasses) and the Scene Manager (SceneConstructor). The constructors for EventManager and SceneConstructor, dependent on each other, tried to save handles to the other which were of course invalid because they hadn’t finished constructing.
All awesome stuff to talk about, so we took the morning to deconstruct and rebuild Jason’s object hierarchy into something that worked. It took about 2 and half hours to do…the bones were in place, just needed a little simplification to make it easier to work with. I figured having a working foundation would be more useful now; Jason can always re-engineer his advanced features in later.
- We got rid of Actions. They were a cool idea to create a meta-language for encapsulating event handling into their own little code objects. But given that Jason had to walk before he could run, we got rid of them and put the event handlers in their own Scheme. Before, Schemes would pass the event objects down to an appropriate Action, after receiving them from EventManager (which was really more of a dispatcher or sorter than a manager). This made implementation much more straightforward
We got rid of the object references carried everywhere. This was something I struggled with when I was new to this stuff also, as I wasn’t that clear on how you addressed what are essentially global variables in OOP without being, well, egregiously global about it. The solution we took here was to define a static method for the
Applicationclass that returned access to the SceneConstructor (the object that manages both movieclips and our custom GUI components).
We simplified the constructors of objects that were co-dependent, letting themselves create themselves first before setting the links.
We combined Scheme and Scene into one thing, each identified by a common SCID. An SCID is basically the “screen name” for a particular screen in the interactive flow. This reduces the flexibility of a “current scene” and “current scheme handler”, but it simplified things conceptually, and I didn’t even grasp that there WAS a “current scheme” until just a couple minutes ago.
We renamed key objects so they were obviously managers, and implemented global constants for things like the SCIDs. We got rid of all those evil string literals. Evil! We renamed other objects that seemed to have ambigious names. That’s also evil.
We pressed the Debugger class back into service. This is a class I like to use for capturing trace statements. They can be redirected to a debug window text area when running in a browser, which is handy. I also insisted on including the name of the class and method invoking
Debugger.Out(), so it was easier to tell where the heck errors were coming from.
After we got it all working, I put the project into Subversion and introduced Jason to the wonderful world of source control. So now, when he goes back to CA, I can continue to review his project, and he gets a way of keeping track of what he’s doing.
p>So now, Jason has a functioning application object hierarchy that allows him to create named scenes with various GUI and MovieClip resources in them. He can add / remove scenes programmatically by making new subclasses of the Scheme base class. That’s pretty darn cool…I’m pleased with his progress since we first started looking at this stuff just three weeks ago. Good job, dude!
We have yet to talk about simulation and animation techniques, but I’m pretty pleased that Jason has gotten the “nuts and bolts” part of making a Flash application from scratch. This foundation should serve him well as he started exploring more development of this kind.
There were a couple of nasty Flash gotchyas that we did have to deal with:
The Actionscript compiler timestamp bugs. Especially when you rename a class or miss it to somewhere else in the hierarchy, and the compiler is confused and never compiles your class again until you clear out the hidden
asodirectory. Every project IDE I’ve ever seen has a “Rebuild Project” or “Make Clean”, or at least is smart enough to give you a
The Actionscript compile problems with circular import. Oh, come on. Had to show Jason the workaround for making a silly intermediate class that links both the circularly-referenced classes.
The sub-1.0 Project Window IDE. This thing is just so primitive. I hope the Flash 8 Pro project IDE improves this. Maybe I need to be looking into Flex instead.
The terrible and unreliable Flash debugger. I applied that “breakpoint in framescript” trick, which allowed me to set arbitrary breakpoints programmatically in AS 2.0 code. But the debugger doesn’t seem to execute statements in-order for some reason…it acts really weird. Too bad. A debugger is a nice tool to have when it works. Must not have been ready for prime time…its interfacing with AS2.0 is very kludgy.