Creating Flash using Ming

PHP uses the Ming library for generating Flash movies, which is licensed under the LGPL. The library is also object-oriented and actively developed by the maintainers. In Flash, all values specifying some form of distance, length, height, or size are in twips, which means a twentieth of a pixel. Flash movies scale to fit their container, though, so these measurements are entirely arbitrary figures.

A Simple Movie

One of the biggest advantages to Ming is that it is object-oriented, so you create a shape object, tell it what color it should be, then add it to the movie. The same process applies for all the other operations in Ming, which makes the code easy to read. Here is a script that creates a basic movie:

$mov = new SWFMovie( );
$mov->setDimension(200,20);

$shape = new SWFShape( );
$shape->setLeftFill($shape->addFill(0xff, 0, 0));
$shape->movePenTo(0,0);
$shape->drawLineTo(199,0);
$shape->drawLineTo(199,19);
$shape->drawLineTo(0,19);
$shape->drawLineTo(0,0);

$mov->add($shape);
header('Content-type: application/x-shockwave-flash');
$mov->output( );

Save that script as ming1.php.

First we create a new instance of the SWFMovie class and assign it to our $movvariable. An SWFMovie object allows you to manipulate attributes of the movie as a whole size, color, animation frame rate, etc. It is also used to add other Flash objects to your movie, so you must hold on to the SWFMovie object that was created.

The setDimension( ) function is an SWFMovie function that allows you to set the height and width of a movie by specifying values in the first and second parameters. Remember that Flash movies generally have their dimensions set in their host application (usually a web browser). The values you specify here are for the movie as you are creating it; however, if the Flash movie is forced to display at a different size, your items will automatically be proportionally scaled to fit the assigned space.

Moving on to the core of the code, we have a new class: SWFShape. Not surprisingly, we use objects of this class to manipulate shapes in Flash movies the process is simply to create, manipulate, and then add to the parent movie object. If you forget to add your shapes to your movie object, the end result is that they'll be missing from the final output, so be careful.

In the example above, the parameter that SetLeftFill( ) takes is the return value of an AddFill( ) call. This is a function of the SWFShape class, and is overloaded (there is more than one version of it). The version used in the example above takes four parametersthe amount of red to use, the amount of blue, then green, and finally, an optional alpha parameter. The fill returned by the AddFill( ) function is used to supply the first parameter to SetLeftFill( ), which is also overloaded. The end result is that the value passed to SetLeftFill( ) sets the fill on the left-hand side of the edgein our example above, this is red.

Next we call MovePenTo( ) and DrawLineTo( ) several times. The movePenTo( ) function lifts the drawing "pen" from the canvas and places it down at the X and Y points specified by the first two parameters, respectively. The drawLineTo( ) function moves the pen in the same sort of way, except that it does not "lift" the pen from the canvas first, meaning that a line is drawn from the last pen location to the X and Y parameters passed into drawLineTo( ), respectively. The drawLineTo( ) function is called a total of four times, giving us a box, and finally we call the Add( ) function of our SWFMovie object, $mov, passing in our new box as the parameterthis adds the new shape to the final output.

The last two lines are crucial to the whole process, and must be used precisely as seen above. The first of the two calls the header( ) function, passing in the correct content type to instruct browsers that the information following is a Shockwave Flash movie. The last line calls the Output( ) function of our SWFMovie object, which sends all the information you have prepared about your Flash movie out to your client. Once you have called this line, your script is complete.

Generally speaking, you will want to embed your Flash movies inside web pages, and that requires inserting the following line somewhere in a HTML page:

<embed src="ming1.php" menu="false" quality="best" bgcolor="#FFFFFF"
swLiveConnect="FALSE" WIDTH="200" HEIGHT="200"
TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/
shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" />

To view your animation in action, load the HTML page into your browser. If your Flash movie does not load at all, there may be an error in the PHP script. When viewing the HTML page, you will not see any PHP warnings, because the Flash movie is being sent directly to your browser's Flash player as part of a larger page. You can work around this by loading the Flash movie directly into your browser you should see the errors printed as normal.

Flash Text

Following the rest of the library, text inside your Flash movie is manipulated using objects. The two key classes here are SWFFont and SWFText . The former holds the actual font shape data, whereas the latter holds information about the text as a whole, including color, position, string data, and the instance of SWFFont used to draw the letters.

The code to generate text works differently under Windows and Unix. First up, Linux users:

$font = new SWFFont("Impact.fdb");
$text = new SWFText( );

$text->setFont($font);
$text->moveTo(200, 400);
$text->setColor(0, 0xff, 0);
$text->setHeight(200);
$text->addString("Text is surprisingly easy");

$movie = new SWFMovie( );
$movie->setDimension(6400, 4800);
$movie->add($text);

header('Content-type: application/x-shockwave-flash');
$movie->output( );

The Windows code isn't far off, and the end result is the same:

$font = new SWFFont("Impact");
$text = new SWFTextField( ); // new!
$sprite = new SWFSprite( ); // new!

$text->setFont($font);
$text->setColor(0, 0xff, 0);
$text->setHeight(200);
$text->addString("Windows is a little harder!");

$spritepos = $sprite->add($text); // new!
$spritepos->moveTo(200, 400); // new!

$movie = new SWFMovie( );
$movie->setDimension(6400, 4800);
$movie->add($text);

header('Content-type: application/x-shockwave-flash');
$movie->output( );

You'll need to alter your HTML file to display the new script, and also change the width and height attributes of the <embed> object so that the Flash movie is larger; otherwise, you will find the text is probably too small to notice.

That code starts with the two new classes, SWFFont and SWFText. The SWFFont class is remarkably easy to use merely pass the name of the FDB file you want to use as a font, and save the return value for later use. You can create your own FDB fonts using Ming's makefdb utility (available from Ming's home page, http://www.libming.org/), so you should replace Impact.fdb in the example with your own font.

In line two of our script, we create a new SWFText object and store it in a $text variable. This object works in pretty much the same way as our previous SWFShape objectwe set various properties of it, then add it to the parent movie once we're done.

The first thing we do with our $text object is call its setFont( ) function, which makes this SWFText object render in the font used to create the SWFFont object specified as the only parameter. In our case, we created our SWFFont object using Impact.fdb, so calling setFont( ) using the new SWFText object will draw the text in this object using the Impact font.

Next, we call the moveTo( ) function to place the text neatly inside the movie, and then call the setColor( ) function (the values are in hexadecimal) to set the text to lime green. The setHeight( ) function sets the height of the text in twips, but again, remember that the final size of the text is dependent on the size at which the movie is played back, and also the dimensions of the parent movie object itselfthe value you set here is just relative to the rest of the movie.

The most important function we call for our SWFText object is addString( )this allows us to draw the string passed as parameter one to the position we set with our moveTo( ) call. It is important to note that the pen the text is drawn with is set to the baseline. If you use moveTo( ) to set the position to 0,0, the text drawn will be drawn outside of your movie.

Actions

Through its powerful ActionScript language, Flash provides a flexible scripting environment to allow developers to take more direct control over the operation and flow of their script. For example, you can call stop( ) to stop playing the movie, then play( ) to continue; gotoFrame( ) allows you to jump to a particular part of your movie, and getURL( ) allows you to browse to a new web page. There is a large collection of actions available to you, and the PHP documentation has some very good (if long) examples on how to make use of various functions.

 

This next script gives you a quick start in using ActionScript:

function MakeActionBox($red, $green, $blue){
$shape = new SWFShape( );
$shape->setLeftFill($shape->addFill($red, $green, $blue));
$shape->movePenTo(-100,-20);
$shape->drawLineTo(100,-20);
$shape->drawLineTo(100,20);
$shape->drawLineTo(-100,20);
$shape->drawLineTo(-100,-20);
return $shape;
}

$button = new SWFButton( );
$button->setUp(MakeActionBox(0xff, 0, 0));
$button->setOver(MakeActionBox(0xff, 0xff, 0));
$button->setDown(MakeActionBox(0, 0, 0xff));
$button->setHit(MakeActionBox(0, 0, 0));
$button->addAction(new SWFAction("getURL('http://www.slashdot.org',
'slashdot');"), SWFBUTTON_MOUSEUP);

$movie = new SWFMovie( );
$movie->setDimension(200,200);

$displayitem = $movie->add($button);
$displayitem->moveTo(100,100);

header("Content-type: application/x-shockwave-flash");
$movie->output( );

That script uses a custom function, MakeActionBox( ), to handle some of the grunt work you will experience when working with the SWFButton class. The SWFButton class, used for the $button variable, has several "states" that each require a shapehow the button looks when it is up, when the mouse is over it, when the mouse is clicked on it, and where the mouse can be clicked on it. Each of these states requires a complete shape of its own, so their creation is automated by using the function MakeActionBox( ).

Going through the main chunk of code line by line, you can see it creates an instance of SWFButton and stores it in the $button variable. Four functions are then called: setUp( ), setOver( ), setDown( ), and setHit( ). These define how this button should look when the user interacts with it. The example is quite short; you will find it is more visually appealing to have more than just the color change between states!

Next we come to the important function of this particular script: addAction( ). This takes two parameters: the SWFAction object to add and a flag for when the action should execute. Options include SWFBUTTON_MOUSEUP as seen above or, alternatively, SWFBUTTON_MOUSEDOWN, SWFBUTTON_MOUSEOVER, and moresee the documentation for a full list.

As the first parameter to addAction( ), we pass in new SWFAction(...). The constructor of the SWFAction class takes a string that contains the ActionScript code you wish the action to execute. For this action, which will execute when the user clicks the mouse button on the object, we want to execute the GetUrl( ) ActionScript function. In the example, GetUrl( ) is passed two parameters: the URL to load, and the name of the window to load it in. If the named window does not exist, it will be created for you. So, the addAction( ) line translates to "Create a new ActionScript action that will load the Slashdot web site into a new window, then attach that action to our button so that it executes whenever the user clicks the button."

After the ActionScript code, there is a slight change to the normal procedure we use $movie->add( ) as before, except this time we grab the return value and store it in the $displayitem variable. This is done because, when adding shapes, text, buttons, and sprites to a movie, the add( ) function returns a special type of objectSWFDisplayItem( )which is a handle to the object inside the movie. This means you can add the same button (or shape, text, etc.) to the movie several times over, and manipulate them individually without much fuss.

This functionality is important because you cannot manipulate the position of an SWFButton object directlyyou need to add it to the movie first, then manipulate the position of the returned SWFDisplayItem object. In the line after the add( ) call, we do just that.

Finally, the movie is sent to output as usual. If you would like to make your button more interesting, you might want to try combining the previous code for manipulating text. To make your ActionScript more interesting, try reading the ActionScript documentation.

Animation

Adding animation to your Flash movies is both fun and taxing. The key to animation is the SWFDisplayItem object returned by the add( ) function of your movie object. SWFDisplayItem objects have a variety of functions that allow you to move, rotate, scale, and skew your objects easily. This next example demonstrates some basic animation:

$font = new SWFFont("Impact.fdb");
$text = new SWFText( );
$text->setFont($font);
$text->moveTo(300, 500);
$text->setColor(0, 0xff, 0);
$text->setHeight(200);
$text->addString("Text is surprisingly easy");

$movie = new SWFMovie( );
$movie->setDimension(6400, 4800);

$displayitem = $movie->add($text);

for($i = 0; $i < 100; ++$i) {
$displayitem->rotate(-1);
$displayitem->scale(1.01, 1.01);
$movie->nextFrame( );
}

header('Content-type: application/x-shockwave-flash');
$movie->output( );

Although that code is largely the same as a previous script, the $movie->add($text) line has now changed so that the return value is captured and stored in $displayitem.

The script then runs through a loop 100 times, each time calling rotate( ), scale( ), and nextFrame( ). Animation works by defining the initial state of the movie, advancing the frame, then specifying changes from the previous frame. In practice, this means you use nextFrame( ) each time you want to move forward to the next frame of your Flash animation.

The rotate( ) function takes a single parameter, which is the floating-point value of the amount to rotate your SWFDisplayItem object from its current rotation. In our example, I have used -1, which means it adds -1 of a degree of rotation with each frame. Because of the way Flash rotation works, this means that the text rotates in a clockwise manner.

The scale( ) function takes two parameters: the amount to scale the object's width and the amount to scale its height. Again, this is based on its last state, which means that the scaling is compounded. By adding 0.01% to the size of our text over 100 frames, we are almost tripling the size of the object.

So, the contents of the for loop translate to "Rotate slightly, scale slightly, next frame" 100 times.








}