Latest AS3 state engine on new area in Google Code
I’ve been plugging away on my AS3 state engine, and with a side-trip through repo-learning land, I think I finally am at a point I can return to the work that I get paid for
!.
In any event, I messed up a Google Code project in my Git experiment, so the new home for the AS3 state engine is http://code.google.com/p/flash-state-engine. I created a simple example to demonstrate it, a digital watch. I will add more examples as time goes on. Thanks to Zjnue Brzavi for his help in combing through the code to reveal bugs that demonstrate I shouldn’t be coding/developing too late at night. He is developing a haXe port, though as I re-implemented the engine in AS3, I also have been mucking around with the API–sorry, Zjnue!
Packaging my Hierarchical State Machine implementation for AS 3.0
It has been a long time in coming, but I am finally getting ready to release our alpha version of our hierarchical state machine for Flash ActionScript 3.0!
I will be writing blog entries over the next few weeks as I document my path to release. It hasn’t been hard to organize things, but I’ve certainly benefitted from finding blog posts about installing or doing this or that.
To begin the process, I created a Google Code project here. I had to choose a version control system for the code, so I chose Git. I was using Tortoise SVN for other projects, but I have heard good things about Git, and the idea of allowing others to fork projects without creating a whole new project was really intriguing to me. I have only had mild encounters with Flex, but I certainly believe that one of the great values in making a state machine implementation is going to be integrating the engine into Flex. However, I’m not the guy to do it well. Therefore, I’m trying to appeal to others who are more familiar to create a Flex fork, perhaps, or maybe haXe, and allow these other projects to influence where I might go with the AS3 implementation. The wonderful thing about not understanding all of this is that I am not limited to what the things actually do, only what I believe they should do
!
I have been developing the AS3 code in FlashDevelop, which is wonderful (needless to say). While of course I have Flash CS4, on my kick-ass iCore 7 Vista machine, the ActionScript editor inside Flash becomes painfully slow with only 1 or 2 pages of code, especially when I start typing things inside quotation marks. I’m now cleaning up the comments and generating the documentation via ASDoc. FlashDevelop has a command to initiate ASDoc, you just have to provide a few key pieces of information. For example, for AS 3, FlashDevelop requires you to specify where asdoc.exe resides. I have Flex Builder and the Flex SDK, so it was simple to navigate over to the sdk/ folder, find the latest version (3.3), and point to it inside the bin/ folder.
The Adobe Flex docs are pretty good for helping to understand the tags for ASDoc.
Flash Builder 4 inline syntax for states looks slick but encourages bad behavior
I’ve been gearing up to dive into Flash Builder 4 and have read a couple of articles about its new features. One that caught my attention was a new, inline syntax for referring to states, e.g., <s:Button label.A="Button" label.B="State B" includeIn="A,B" />, to switch the label for the button depending on the current state (A or B). As Jon Rose explains it:
The legacy state syntax in Flex 3 required components and properties to be modified within the state block. This was out-of-context, often verbose, and frequently confusing. Flex 4 introduces a new inline syntax that is both flexible and terse.
Not to single out Jon, because I saw it in other articles as well, but it points to a lack of understanding of one of the strengths of a state-based approach: all the code for a state is contained in the same location, and hence it is much easier for the developer to understand what the application does in that state. The new, inline syntax for states allows developers to sprinkle behavior related to different states on the same element, which means if one wants to understand the overall behavior of a state, one has to examine all the potential elements.
I was particularly struck by Jon’s comment that because “Flex 3 required components and properties to be modified within the state block”, it was “out-of-context” and “frequently confusing”. That sounds strange to me, because requiring changes to be enclosed in the state block actually is the correct context, namely things that happen in that state, where one looks for information about how that state behaves!
Admittedly, I have not really worked in Flex 3 or Flex 4 (yet), but I believe the concept of states should transcend the development platform. Therefore, I have to give a ‘thumbs down’ to this new inline syntax for states.
Update…Getting Close to Clearing My Schedule
It’s been a hectic past few months as I’ve been working on small projects and not getting a chance to get my head above water. It’s been hard to make progress on advancing technical work when there is so much business organization, marketing, and sales work to accomplish.
I’m almost at a point I can return to some technical work to get more of my libraries over to AS3. I will be posting as I get deeper into this…
Correcting immediate event posting “feature”
As I consider the AS 3.0 implementation, I will address another small issue that occasionally crops up — the fact that events are handled immediately in my 2.0 architecture, rather than queued for processing.
The reason they are handled immediately is obvious when you consider how it is done — anyone sends an event to the event handler. Really, anyone. So this could be a routine handling an event already that sends a new event. The problem is that the original event really should complete before posting the new event. Most of the time this has little to no consequence, but it has to do with the run-to-completion concept from UML statecharts.
I think the correct thing to do is to have a new method, postEvent, which routines can use to post an event to the system. If the main event handler is currently processing an event, it will queue the event until it is done (and then process the event). I think I should also allow an optional delay parameter (msec or frames), kind of a concession to Flash, which would delay the processing of the event at least as long as (but perhaps longer than) the caller requests. The concession is to how Flash updates the graphics, on a frame basis. If someone has set up states tied to frames, they may want to wait until the frame is active before executing the stuff within the state. We’ll see!
AS 3.0 State Machines
I’ve been meaning to write about this for some time, because occasionally people ask me about whether I am going to port my state machine to AS 3.0. The answer is yes, but I just don’t know exactly when [Aug '09 Update: I did it! see #3]
Those looking for state machines in AS 3.0 should check out:
- Troy Gardner’s COGS (http://code.google.com/p/troyworks/) framework, which is based on Miro Samek’s (http://www.state-machine.com) QHsm and QFsm work — people know I’m a big fan of Miro’s.
- Bill Sanders’ State Machine design pattern, from his excellent book, “ActionScript 3.0 Design Patterns” — not a hierarchical state machine, however.
- [* New *, August 17th, 2009] My As3 Flash State Engine, http://code.google.com/p/flash-state-engine/.
Certainly if anyone knows of others, please let me know!
Event handling for FStEng 3.0
I’ve been planning to port my FMXIS State Engine from AS 2 to AS 3, but haven’t really had the time to think about how I want to improve the system rather than just translate it. This is an opportunity to rethink some things I didn’t like about the current (2.0) architecture, so I don’t want to waste the opportunity.
The main thing I plan to upgrade/modify is the way events are distributed, both to make it fit in the AS 3.0 model of events, and to avoid what I must do now to get the current event handling behavior, which is to make the state class dynamic — I think one of the reasons I’ve put off doing a 3.0 port is that I hadn’t solved how to keep the event handling I like while sealing the state class.
The Current State of Things (No Pun Intended)
Currently, an event that comes into the main event handler routine (ieh, for internal event handler) is identified by a string, a value, and a pointer to who generated the event. The main event handler has what I call a “trigger table” that converts the incoming event into an event that one or more states or transitions want to use to trigger a state-internal action or a state-changing transition. The trigger table processes an incoming event and filters it, essentially.
For example, an incoming event might be a certain button press, and a state or transition may be waiting just for that to happen, so there’s no real conversion. However, a state or transition might be waiting for a knob to reach a certain value — that is an event derived from a subset of all events from that knob. The effect is that the trigger table is used to convert an event name and value into a potentially new event that some of the states or transitions have declared they want to use to initiate actions or transitions (hence the term, “trigger”).
What has bothered me is how to convert to 3.0 the current way of declaring that states want to handle events. For example, if a state wants to execute something on a certain button press, we write
myState.someButtonPress = function () { ... }
I like this format because I think it is easy to understand. In the trigger table, we have added an entry like:
someButtonPress : function (m) { return (m == "button1"); }
which means that our specific button has sent an event in called “button1″.
Internally, the state doesn’t really keep a someButtonPress method — the internal processing adds a filter that says “if the conditions for someButtonPress exist, trigger the corresponding function”.
The problem from a 3.0 perspective here is obviously that the state class would have to be declared dynamic to permit “myState.someButtonPress”. That’s a big price to pay considering now that ActionScript has the real ability to seal a class (unlike in AS 2.0, in which it would be limited to compile-time checking).
Making States the 3.0 Way
So I like the idea of the trigger table — a mechanism for filtering events — but I want to avoid making the state class dynamic. The best solution I’ve come up with is to make actions and transitions register as event handlers for states. This is more involved than the original way, but it is consistent with the AS 3.0 event model, and it lets me keep states sealed.
For the example above, instead of (from above) myState.someButtonPress, we will write:
myState.addEventListener(SomeButtonPressEvent, function () { ... })
or
myTransition.addEventListener(SomeButtonPressEvent, function () { ... })
which are a bit more complex to look at, but I think in line with what we need to accomplish. This still means I need a concise way to filter events and generate new ones (the trigger table processing), but I think that is manageable.
