I also want to give some credit to the person and website where I got the idea. I was at the FriendsOfEd.com site checking out some of the new Flash titles, specifically "Foundation Actionscript 3.0 Image Effects" by Todd Yard, because BitmapData manipulation is not one of my stronger skills at this point. I followed some links to Todd's site at 27bobs.com, where I found his tutorial on capturing motion. The example was written for Flash 5 and used onClipEvents. I did not read much of the tutorial. I only flipped through it until I had an "Ahh Ha" or "No Duh" moment when it was mentioned using arrays to store x and y locations. I do not know what he did after that. I like to figure out the details on my own. Besides, I don't think it would have helped much looking at all that old code. Sometimes it is just easier starting from scratch. I also want to use some Flash Player 10 specific code before the process is done.
First let's look at the results. My first example is at http://www.richhumphreys.com/flash-experiments/recording-animation-1.html. Just follow the instructions to test it.
Now that you see where we are headed, let's see how to get there.
- We need some assets to play with. This version has a background image and a translucent bitmap image for the bee, but all we really need is a MovieClip and some buttons (I got mine from the Flash Common Libraries found in the Window menu. The two buttons just get added to the stage and given the instance names of "play_btn" and "record_btn".
- Go to the Properties panel for whatever symbol will be your moving object and export it for ActionScript. I gave mine the class name "Bee" and just left the default Base class as MovieClip. (If I were creating hundreds of these, I would probably change it to Sprite) We will be adding this using the ActionScript addChild method.
- Now create a new ActionScript file and call it MotionRecorder.as
- Add the skeleton of a Class file.
package
{
public class MotionRecorder extends MovieClip
{
public function MotionRecorder():void
{
{
}
}- Before the class statement, import the classes we will need for our Class
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.geom.Point;- Create variables for our Bee object, a boolean called "recording" to keep track of whether we are recording or playing, an Array called "points" that will hold the recorded information, and a variable called "playPosition" which will call up the correct indexed value from the Array.
private var bee:Bee;
private var recording:Boolean = false;
private var points:Array = new Array();
private var playPosition:int = 0;- In the constructor function we add a new instance of the Bee object from our library to the stage and give it an x and y location. We also add MOUSE_DOWN and MOUSE_UP event listeners to the bee instance and CLICK events to the record and play buttons.
bee = new Bee();
addChild(bee);
bee.x = 350;
bee.y = 375;
bee.addEventListener(MouseEvent.MOUSE_DOWN, onMousePress);
bee.addEventListener(MouseEvent.MOUSE_UP, onMouseRelease);
record_btn.addEventListener(MouseEvent.CLICK, skinButtonClick);
play_btn.addEventListener(MouseEvent.CLICK, skinButtonClick);- Our first function is to handle the play and record buttons. It simply tests to see which button was clicked (using a switch). If it's the record button, we empty the points Array and set "recording" to true. If the play button is clicked, we tell flash we are no longer recording and start an ENTER_FRAME loop to create our playback.
private function skinButtonClick(event:MouseEvent):void
{
switch(event.target.name){
case "record_btn":
points.length = 0;
recording = true;
break;
case "play_btn":
recording = false;
addEventListener(Event.ENTER_FRAME, onLoop);
break;
default:
points.length = 0;
recording = false;
}
}- Our next two functions handle the MOUSE_DOWN and MOUSE_UP events and add the drag and drop functionality to the bee. If recording is set to true, the onMousePress function starts a loop to allow for recording each frame. The onMouseRelease function stops the loop by removing the ENTER_FRAME event listener.
private function onMousePress(event:MouseEvent):void
{
if(recording){
bee.startDrag();
addEventListener(Event.ENTER_FRAME, onLoop);
}
}
private function onMouseRelease(event:MouseEvent):void
{
removeEventListener(Event.ENTER_FRAME, onLoop);
bee.stopDrag();
}- The last function, onLoop, handles both recording frames of motion and playing them back. If recording is set to true, the function adds Points to the points Array, recording the x and y locations each time the loop runs (at the file's frame rate). If recording is set to false, the loop moves the bee MovieClip to the x,y location specified by the Point at the current index setting according to the playPosition variable. We increment the variable and continue until we run out of items in the Array. When we run out of items in the Array, we remove the event listener (thus stopping the looping) and reset the playPosition so we can run it again.
private function onLoop(event:Event):void
{
if(recording){
points.push(new Point(bee.x, bee.y));
} else {
if(playPosition < points.length){
bee.x = points[playPosition].x;
bee.y = points[playPosition].y;
playPosition++;
}else{
removeEventListener(Event.ENTER_FRAME, onLoop);
playPosition = 0;
}
}
}That's it. The record button tells the script to add to the Array and the play button tells it to read from the Array.
For the full ActionScript file go here.
In the next post I will look into how we can make this code run with a few new features of Flash Player 10.
One last thing... Since I did not have a photo of my own that fit my needs, I turned to Flicker and used one by adulau. Thank you adulau for using Creative Commons rights and allowing your file to be modified, and having some cool pics to choose from.
No comments:
Post a Comment