We at
Exopolis just launched this today:
This is a hybrid Flash/Flex app that allows you to select robot parts (including a heart, which represents a musical track) and assemble them into a dancing robot which you control with the mouse and keystrokes. I have to say—I spent hours making this and it's
still fun to me.
I'd actually started something similar back in
Flash 4, if you can believe that. Yes, before true ActionScript. I had to manually create a sine lookup table. It was fun.
After a couple of false starts in intervening versions of Flash, I finally had my greatest success with a Flex version. Dynamic binding makes this sort of thing
so much easier.
Basically, the way the robots work is that each joint is associated with a type of object called a
Locator. Minimally, a
Locator stores a point, dispatches updates whenever that point moves, and allows that point to be constrained. A
Locator can be created as simply as:
<Locator id="myLocator" x="100" y="100"/>Of course, that's not a very interesting
Locator, since it doesn't move. Moving a
Locator can be done in one of two ways. One way is to extend the basic
Locator class, creating a specialized type of
Locator. As an example, one of these is
StageMouseLocator:
<StageMouseLocator id="mouseLocator"/>The
x and
y properties of this
Locator always correspond to the position of the mouse. If I wanted to bind another
Locator to this, I could do it like so:
<StageMouseLocator id="mouseLocator"/><Locator id="myLocator" x="{mouseLocator.x}" y="{mouseLocator.y}"/>Voila, now
myLocator follows the mouse. Why would I want to do this when
mouseLocator already does that? Good question. I wouldn't. But now I can do stuff like this:
<StageMouseLocator id="mouseLocator"/><Locator id="myLocator" x="{mouseLocator.x + 100}" y="{mouseLocator.y}"> <constraint> <constrain:VerticalConstraint minY="100" maxY="500"/> </constraint></Locator>Now it will always be 100 pixels to the right of the mouse, but it will constrain the vertical position to between 100 and 500 pixels in the display's coordinate system. You can see how this sort of binding with modification can lead to more complex behavior.
Another way to control a
Locator object is by using an (aptly-named)
Controller object. One such object is a
SineController object:
<control:SineController id="beatController" speed="0.25" context="{this}"/>This keeps an angle value, updates it on every frame (incrementing by 0.25 radians) and makes the sine value available through a property called
sine. So if I wanted a controller that followed the mouse but oscillated up and down, I could do this:
<StageMouseLocator id="mouseLocator"/><control:SineController id="beatController" speed="0.25" context="{this}"/><Locator id="myLocator" x="{mouseLocator.x}" y="{mouseLocator.y + beatController.sine * 50}"/>Of course, I have other types of
Controller (
StepController, which extends
SineController;
RandomController;
ClickController; etc.), other types of
Locator (
JumpLocator,
JointLocator,
InterpolatedLocator,
ModeLocator, etc.), and other types of constraints (
DistanceContraint,
RectangularConstraint, etc.). All of these I blend to create a basic skeleton of points.
Once I have the skeleton, I can attach various visible objects call
Connector objects, each of which connect to a number of points and have rules for "squash & stretch". The robots all use
MovieClipConnector objects, which each link a Flash movie clip to one or two connectors. I also have
DrawnConnector,
ImageConnector, etc., and hopefully I can use those on future projects.
I had actually started to make this as an application where you would sketch your own character and it would animate according to a skeleton, but this turned out to be much too processor-intensive, at least for now. Fortunately, one of our senior designers, Chuck Chugumlung, had this idea for a dancing robot factory and he and some other designers (Dan Duran, Jancy Liu), went to town.
Anyway, enough geekery. Go make some robots dance!