Categories Displayed in Flash

Archive for the 'Cogs' Category

AS3: Prelude to Tweeny, a fast and flexible Tweening engine

So I've been working over the weekend on the Tweening engine based on Cogs affectionately called Tweeny. I find it highly amusing as I've been working in Flash since Flash 4, I have built so many presentation engines it borders on comical when every new client inevitably asks for a powerpoint lite clone, and consider myself relatively advanced,..yet how much of a loop this one threw me for.

WhileI had an AS2.0 class already working, it's taken me 3 days to get the basics working in AS3.0. This is because yesterday I totally got schooled on Matrixes with Senocular's most excellent tutorial, (my brain still hurts) and then excited by Penner's lurking MatrixTransform and ended up scrapping several paragraphs that comprise most the standard tween engines. I find myself building this next presentation engine in a way that bears no resemblence to most engines I've used or seen, partly due on the architecture difference between AS3.0 and prior, and partly expanding the role of Tweening beyond the simple display classes. Every time I added a new feature or solved a bug, I found a way to make things simpler.
Matrixes are cool, as you can get away with just easing the Begin and End matrixes rather than doing every calculation, plus you get the ability to offset the registration point and skew, features both very useful for the Authoring type interfaces and kids content I'm creating. More power and more speed to boot! In running performance tests, it's about 2x faster than setting DisplayObject.rotate, DisplayObject.width, scale etc as most tween engines do. Not that running those scripts are typically the limiting factor relative to the overhead in rendering, but still it's nice to know that the underlying code isn't a bottle neck.
Like most Tween engines, Tweeny supports a pluggable easing that affects multiple properties (x, y, width etc) with individual ranges (x[-5, 100], pan[-1,1]). But something my math-whiz girlfriend help me realize was that since duration is fixed, the easing equasion (often filled with expensive Math operations) can be calculated once as the 'normal' and then scaled to the others ranges, cheaply with simple * + . This should significantly reduce tweening calculation overhead,...and dammit I like smart particles flying at 60fps!

To further that I realized that the normalized calculation, is easy to broadcast, so that other listeners keep in synch, and can conceivably modularize or patchwork tweens. One of the things that I've wanted to try for awhlie was a way to balance out top-down easing approaches with bottom up physics routine. This usually involves Euler or Verlet accumulation and integration of forces, but most tweening engines are rather possessive when it comes to updating display objects...only one at a time else they start overwriting, where's the fun in that?
Some other features I like, Sound or SoundChannel volume and pan, colorTransform tweening (which I use a lot for configuration dynamically styled UI's) easier constructors for Bounce and Elastic's extra params which I use with kids games.

One thing that I'm not currently planning on supporting soon is a JSON or XML based interface. I find it poor programming practice to do

TweenEngine.create(target, duration, {x:1,y:2, ....})

in AS3.0 when you can do:

var t:Tweeny = new Tweeny();
t.initFrom(target,duration);
t.x = 1;
t.y = 2;

t.addEventListener(...)

t.startFromBeginning();

Because using fully typed classes allow for autocomplete to help fill out the values, offer stricter type checking and setting of defaults. When they are on a line by line they are easy to comment out to turn on and off. There isn't any overhead to parse XML or JSON into useable values. Since it's part of the Class definition it should also be significantly faster than dynamically allocated Object properties on the prototype.
Keeping a tween around, keeps memory and garbage collection from churning, especially for most applications where the tween is reused over and over again to put thing back and forth. I realize why many tween engines opt not to go this route as managing transitions on top of other transitions can get tricky. But know that I know about these issues I'm glad I spent the extra time. Since Tweeny uses the Playhead API, it supports stop, rewind, play, playbackward etc, it's not really different than keeping an mp3 or swf around.
So far it's about 10K, so 3x larger than say Tweenlite, but much of that is the inclusion of the framework/Cogs is useful for many other things, websites and games especially, and I'm still working on it.
The morning had an epiphany and I was able to tie together many of the related ideas into a cohesive model, so I have a roadmap for the next few months, and even a relatively simple Authoring UI for all the features exposed. Looking at the one pager of noteobook, probably 7 boxes, and only a few UI elements, in that largely what I'm working on is creating much of the same metaphors (e.g. timeline) of Flash inside of Flash...just like Web 2.0 is largely recreating the OS inside of the WebBrowser. And Virtualization is recreating the connectivity of electronics. One that note, if your looking for good book on self-referentiality check out Gödel, Escher, Bach .

Agile vrs Model Driven Design

Here's another vote for where Cogs and the related framwork comes in handy

http://joeberkovitz.com/blog/2007/05/17/software-modelling-soft-focus-or-hard-edges/#more-55

I don’t think of MDA ("Model Driven Architecture") and “agile” methods as necessarily opposed to each other. Modelling, whether it’s UML or some other system, can serve several good (and potentially agile) purposes:

snip..

2. Some models are far simpler than the corresponding structures in the target programming language, in which case code generation from a model may save a lot of needless work. Complex state machines are an example.

This I totally agree with, and Cogs (or any decently written FSM/HSM engine) will allow this from the boardroom to the code room, to testing and most importantly back, even with new teammembers, without huge impedences. It allows the two strategies, plan ahead, or discover along the way to be used in tandem and at different times.
The basics are that modelling if known ahead of time can save huge amounts of work provided the models actually correspond to the problem domain..provided they are known, frequently they aren't precisely and that's where the devils in the details come in. When properly used, they bypass the expensive rediscovery process, rebuilding from first principals, and facilitate communication. Design patterns is all about this, a library of frequent solutions. Cogs and the use of state machine libraries just extends this to the time domain.

Some things are truly novel, but common application behavior like registering and logging in to quitting the service, or all the possible states of a media player have been done a million times or more, some have tricky aspects that one doesn't discover until one is chin deep in the mire, and like the wheel don't really have any benefit from rediscovering..with a chisel how long will it take you to make a wheel that is perfectly round?. State charts are design patterns for behavior over time and they transcend any particular language, and useage be it parsers, game AI, components or web applications. These patterns are a good place to start in the Information Architecture phase, by considering how the application you're developing is different, it can expose the unknown rollercoaster you are about to code for...and reveal states that may be important you didn't even know you needed to know.
While these patterns could be implemented in a number of ways, at a code level, Cogs (and any HSM) and related libraries are just the most compact representation of the problem in code, much as compression of data finds common patterns in a file and compacts them. Less code leads to less issues, faster development, and less bugs to track, and a better idea of where to fit them in.

Back to the architecture phase, excess modelling can be *superevil*, it's an evil of preoptimization in projects, and arrogance on the behalf. Designing optimizations before actual use is known, which frequently requires dramatic rethinking when this is discovered (this is especially true for projects not grounded by user testing in how end users...not the design and tech geeks building the app will actually interact with it). Such ungrounded, it's easy to ask silly questions that seem important and design around imaginary concerns (let's design sunglasses to protect against the evil green sun!), as many projects aren't chess matches with a known winnning position, once released into the wild the game changes to checkers: same board, different strategies and pieces.
This swings back to the advantages of using agile development approaches: test first, design to fit the test, be ameniable to change, iterate lots. Which using Cogs, ActiveFrame, Sketch do as they are based on years in the trenches looking at how and why applications fail to scale, providing a bridge between rapid prototypes to build team consensus (both inhouse and clients) to compelling usable end-user oriented end products. But here, testing first can lead to taking as long as evolution did to get things useable, let alone right. So the solution is somewhere inbetween.

Flow charts and statecharts are good place to start or pause along the way, because being visual language, anybody can participate, from domain experts to designers to tech. in addition, because modelling an application without considering state and behavior over time is pretty fool hardy, kinda like saying your planning a trip that requires a car, anda single tank of gas, but no idea of where your going. Since COGS uses very few words to descibe a state, and it's actions, there is almost a 1 to 1 representation between the diagram (minus layout aspects) and the underlying code and documentation. More detail of course in the code since it reflect the actual path, rather than just the map. But compared to classes based approach with tons of files scattered, it's generally easier to read, and thus pass the torch as needed when projects are handed off.

Introduction to ActiveFrame, Cogs, Chain, Score, Sketch, fXperience

Intro to StateMachines

The good news is if your in team development, you've been diagramming them for years, as flowcharts and bubble diagrams. Bubbles are states, arrows are transitions. This is one of the keys to their usefulness in teams. The diagrams can be understood and modified by anybody, and can represent anything from a users interaction with the whole application, a game's AI, or the graphical transitions in a button rollover. Any Animator who has done keyframes and tweens knows has been unwittingly using states and transitions, but what about developers?
Most any application developer is familiar with OOP, and many design patterns like the State Pattern. Some may have heard of the term finite state machine (FSM) with a possible vague understanding of what one is/does, most are probably not familiar with Hierarchical state machines (HSM), which are especially powerful, especially in experience driven, Flash
and AIR content working with asynchorous network requests, and large media upload/downloads, long timeline, all of which have complicated life cycles with asynchronous call/callback.

I started using them in projects after first learning about them in software from Jonathan Kaye. After using a few different versions in a few different projects, and developing my own, I have been on a quest to spread the word ever since. OOP and SM's foundational aspects. They are orthogonal and complimentary, OOP describes the nouns of the system StateMachines's the behavior over time. An example the cat is meowing, cat is the noun, meowing is the current state, and it will change over time.

Intro to Cogs
Cogs is the AS3 library of statemachines, and common patterns that people can extend/plugin similar to how people reuse design patterns, to avoid reinventing the wheel. Just as in Design patterns, there are fundamental patterns, from simple toggleable button, to synchronized media players.

It's named Cogs first after the tiny teeth that compose gears, that when meshing properly make up engines which power most the mechanical world, and secondly Cognition as the meshing of neurons make up the engines of intelligence. Cogs primary use is increasing the intelligence of components, games, game AI, and applications, by several approaches:

Cogs allows you to ask where you are, where you can go, and automate chains of execution between two states. Often event driven components are black box event generators, identical events broadcast at different times mean completely different things (like NetConnection) this is far from simple.

The FSM and HSM are based on Miro Samek's approach of using functions instead of classes to represent states, this very low level implementation has several advantages, one of the first is being less code to understand and write. It also enables behavioral inheritance, similar to. Cogs is different in several ways from Miro's inspiring work in his book. First all possible transitions are supported instead of just the common ones, and are validated by the unit tests..and the testing framework itself being an FSM and supporting Asynchronous testing easily.

Ongoing I'm working on API's for deep history, serialization/deserialization a graphical visualizer, among other things.

ActiveFrame

Cogs is part/foundation of a larger framework named ActiveFrame. Which strives reduce commmon architectural decays, largely by decoupling.

  • A message bus enabling event decoupling,
  • Java Spring 'Dependency Injection' for Implementor Interface decoupling,
  • plus a decoupling of the UI and controller..which can live in completely different swfs, similar to AS2.0's Object registerClass.

It's reasonably small for all these features, allowing it to be used for components, games, game AI or full blown applications.Sketch

is the visual extension of the Cogs, to deal with the View/UI world (e.g. movieclips/timelines, sprites), common layout, and UI/controller decoupling communication. While Sketch can be used whereever Flash can go, it's strong points are design and script heavy projects, in teams that have strong separations between design and scripting... they don't even have to be working on the same file.

Since it's based on Cogs, it's very easy to prototype and if flow diagrams (state diagrams) are used in the IA and Creative phases, it can act as a common language between design, IA, and engineering, as diagrams can easily be translated to code and back, and reworked easily. It supports what I call "introspectable UI's", in that the statemachine can act as the model, and summarize all the active states supported options to generate an appropriate "where can I go from here" UI.

Chain

is the workflow component, it's coordinates dependent parallel and sequential and nested tasks, with asynchrous call/callbacks, providing status along the way. Some uses for this are preloading assets, playlists, unit testing, easing and tweens, build out and tear down of UI's.
Score

is the the parallel timeline orchestration component, similar to a Orchestral score for coordinating multiple instances with a single virtual playhead. Useful for overlapping events. It's similar to an actionscript version of the Flash IDE timeline.
fXperience

is the visual components library. This is based off Cogs/Sketch, components have a wider lifecycle than those built into Flash and Flex., e.g. a button transitioning in, transitioning to up, transitioning to over etc. They support easy and iteratible skinning, so projects can start out simply as a graphic than graduate to more complicated ones as need requires.

Misc

All are a part of the TroyWorks AS3 code library that is MIT licensed on google (but isn't finished/uploaded yet, API isn't stable) There are many other useful utilities, datastructures and components of interest I'll be covering in more detail as they get more fully flushed out and converted to AS3 from AS2, I'm trying to make sure I don't add something already in AS3, and take full advantage of AS3's architecture.

Introspection in AS3: use of namespace

As I was mentioning in the last article, I was looking for ways to introspect code without resorting to use of 'public' access modifier /namespace.
This is for a particular project/framework named Cogs which I'll be covering more. Cogs is a statemachine, and allows for multiple active states, similar to putting animated movieclips inside other animated movieclips. Cogs uses functions in a very unique way, in that every function is a 'state' similar to a frame in Flash, and every state has events similar to 'enter_frame' and 'exit_frame'. A variable maintains a link to a current function, and passes events to it. So a Person class might have the following lifecycle, each state corresponding to a function.

  • s_eating(evt:Event); //parent is s_awake
  • s_awake(evt:Event); //parent is s_alive
  • s_sleeping(evt:Event);
  • s_alive(evt:Event);
  • s_dead(evt:Event);

While Cogs has a reference to the current state (say eating), which bubbles events. If scoped to the public namespace, apps using Persons could inadvertently call other inactive states directly , causing undersired responses, when preferrably unauthorized calls to the function shouldn't compile at all.
Say if the person is currently in the 'dead' state, and someone asks "How are You?" Event/Request, it doesn't reply, but if they call s_awake, it might respond/trace "great!".Normally
Part of the problem somewhat unique to using Cogs's is validating the hierarchy making sure there are no dead ends. E.g. this is a good heirarchy.

  • Root
    • Dead
    • Alive
      • Sleeping
      • Awake
        • Eating

This would be a malformed one.

  • Root
    • Dead
    • Alive
  • Awake
    • Sleeping
    • Eating

flash.util.Proxy
So I was originally going down the path of using flash.util.Proxy's neat feature to 'iterate' over an object thinking it had special powers of visibilty with all it's capabilities of overriding iterators and the like. When actually it is just a Proxy, relaying requests to variables and methods frequently of child attributes/methods, other than itself.
Proxy in use should be composition primarily instead of inheritance. It's supposed to wrap other classes instead of be the class. This is kinda a way to achieve the appearance of multiple inheritance, via proxying requests to multiple classes. Anyway the for..in and describeType limitations still apply, there is nothing magical about the namespace/scope of Proxy or flash_proxy other than they aren't public so won't collide if methods are similarly spaced. However I noticed that tracing out methods namespaced to flash_proxy were showing up on the describeType. Which game me a clue to where to go.

AS3 namespace, creating, using.

The documentation on namespace in regards to AS3, and multiple classes is a bit hard to find. Especially on the web/google. But it's very cool (check the Flash CS3 help for examples)

starting here

http://livedocs.adobe.com/flash/9.0/main/flash_as3_programming.pdf

and here

Here's the basic steps to creating and using namespaces. Quote:

There are three basic steps to follow when using namespaces. First, you must define the
namespace using the namespace keyword. For example, the following code defines the

version1 namespace:
namespace version1;

Second, you apply your namespace by using it instead of an access control specifier in a
property or method declaration. The following example places a function named
myFunction() into the version1 namespace:

version1 function myFunction() {}

Third, once you’ve applied the namespace, you can reference it with the use directive or by
qualifying the name of an identifier with a namespace. The following example references the
myFunction() function through the use directive:

use namespace version1;
myFunction();

You can also use a qualified name to reference the myFunction() function, as the following
example shows:

version1::myFunction();

What this doesn't cover is how to create namespaces, and URIs. The help documentation has two types of namespaces, that primarily used for XML and that used for actionscript visibility even though underlying they are probably the same thing. It took me an hour to figure out how to figure out how flash_proxy namespace was implemented, as that's not covered directly.

I created two folder/packages Test and Introspectable, Test containing the main executeable and Introspectable having a namespace, and a class that uses namespace to limit visibility for variables and such. My first goal was creating a namespace that is visible to multiple classes in multiple packages silmiar to flash_proxy, which was the trickiest part, as it's not a class. But rather AS3's somewhat unusual ability to import straight functions/etc. Similar to #include in AS2.
//FILE1: Introspectable/introspectable.as

package Introspectable {//note that default URIs are {package}.{namespace defined in this file}
//e.g. URI Introspectable.introspectable but I'm overriding it with URI of "com.troyworks.cogs"
public namespace introspectable = "com.troyworks.cogs";
}

//FILE2: Introspectable/

package Introspectable{
import Introspectable.introspectable;

public dynamic class IntrospectableObj {

introspectable var introVar:Number= 0;

introspectable function s_introspectable():void{
trace("Hello World from introspectable::s_introspectable");
}

//File3: Test/Test_DescribeType.as

package Test {
import flash.display.Sprite;
import flash.utils.describeType;
// import Introspectable.*;
import Introspectable.IntrospectableObj;
import Introspectable.introspectable;public class Test_DescribeType extends Sprite{

public function Test_DescribeType(){
super();
var intro:IntrospectableObj = new IntrospectableObj();
var desc:XML = describeType( intro);
trace("Test_DescribeType \r" + desc);
// use namespace introspectable;
intro.s_introspectable();

OUTPUT

note you can see the ones with the custom namespace in describe type, but since we haven't specified a namespace, calls will get an error 1006 'is not..'

TypeError: Error #1006: s_introspectable is not a function.
at Test::Test_DescribeType()[C:\DATA_SYNC\CodeProjects\Flash Work\as3 - introspection\Test;Test;DescribeType.as:28]
at [execute-queued]

Uncommenting the line

use namespace introspectable;

and running again allows the function to call successfully:

Test_DescribeType

variable name="introVar" type="Function" uri="com.troyworks.cogs"

method name="s_introspectable" declaredBy="Introspectable::IntrospectableObj" returnType="void" uri="com.troyworks.cogs"

Hello World from introspectable::s_introspectable

Which is the desired result of custom namespaced items that can be introspected and called but not without specifying the namespace up front.