the informal ramblings of a formal language researcher

Saturday, November 05, 2011

A Bit of Trignometry

So I wanted to aim small for my initial foray into using Flash Professional to make a small bit of example code for this blog.

(I have done some small proof of concept stuff in Flash Pro and in Flash Builder before, mainly to explore the runtime garbage collector or illustrate short-comings in our ActionScript API's. But none of that has translated over to blog content here before.)

I figure that in general I'll need to be able to render animated text and shapes. Other functionality (mouse event handling, UI elements like buttons or text boxes) can wait for later.

So okay, how about "Hello World," where the text does something interesting. Like rotate 360 degrees in a tight circle around its mid-point; that's the kind of thing that is really easy to show off in DrRacket.

It was easy to get started: a few mouse clicks to select the text tool, create a "Hello World" text object, and make it rotate continuously.

  1. Choose the menu item "File → New..." and choose "ActionScript 3.0" in the New Document dialog window.
  2. Now that you have a fresh blank slate to work with, select the Text tool in the toolbar on the right hand side of the screen:
  3. Create a fresh text object by clicking the Text tool on the white space (the "stage") on the left hand side of the screen:
  4. Create a fresh text object by clicking the Text tool on the white space (the "stage") on the left hand side of the screen:
  5. If you like, you can automatically align the text to sit in the center of the stage, in four clicks: the first to open up the alignment controls, by clicking the "Align" button in the menu bar at the center of the screen, the second to turn on the "Align to stage" option in the alignment controls, and the third and fourth to turn on the "Align vertical center" and "Align horizontal center" options.  The latter three steps are illustrated below:


  6. Finally, to make the selected text actually act in a dynamic fashion, double-click one of the premade ActionScript snippets, found in the "Code Snippets" that you can select from that middle menu bar again. For this experiment, I selected the "Rotate Continously" code snippet:
  7. You will probably get a pop-up dialog box saying that this code snippet requires an instance name; just click okay and Flash Pro makes up a name for the text object.  And voila:

Except when I tested this (menu item "Control→Test Movie→Test"), I did not get what I expected:

Yes, this text is rotating in a circle... but not around a point in the middle of the text.

The reason is simple: the text object's position is determined relative to the (x,y) coordinate at the upper-left hand corner of the text.  When you rotate the text, it rotates around that origin at its upper-left corner, so that corner is what it rotates around.

This discovery turned a somewhat silly test of Flash into a slightly more meaty (though mechanical) puzzle: how do I get the effect I wanted originally.

The answer: Trigonometry!  As the rectangle rotates, we also adjust the position of its upper-left corner, moving it in a circle in synchronization with the rotation of the rectange.


(The above picture has flaws; in particular, the line segment r is supposed to end at the center point of the rectangle, but it clearly does not, since the horizontal line going through it is vertically above both the lower-left and the upper-right corners. This should not be possible if that line were truly going through the center of the rectangle. In my defense, this was my first foray into using Adobe Illustrator. I will probably try again later using TikZ/PGF.)

This derivation leads to the following change to the ActionScript code that Flash Pro inserted for us:

textField_1.addEventListener(Event.ENTER_FRAME, fl_RotateContinuously);

var w = this.width;
var h = this.height;
var r = Math.sqrt(w*w/4+h*h/4);
var theta = Math.asin(h/(2*r));
var origin = {x:stage.width/2, y:stage.height/2};

function fl_RotateContinuously(event:Event)
{
   alpha += 0.1;
   var psi = alpha + theta;
   var dx = r * Math.cos(psi);
   var dy = r * Math.sin(psi);
   // trace(w,h,dx,dy);
   textField_1.x = origin.x - dx;
   textField_1.y = origin.y - dy;
   textField_1.rotation = 360*alpha/(2*Math.PI);
}

And, voila, for real this time:

No comments:

Followers