43 posts
Showing 20
| Next
(page 1 of 3)
How to Build a Flash Video (FLV) Progress Bar (Part 2)
Posted Tuesday, July 10, 2007 9:20:35 AM by David Stiller
In Part 1, not quite a week ago, we looked at a relatively simple way to track the progress of an FLV file as played without the FLVPlayback Component in a SWF. Here in Part 2, we’ll make the knob draggable, causing the video to seek to the point in time that corresponds to the knob on its track. As it turns out, the ActionScript involved doesn’t change all that much. It may look like a lot more code, but the mechanics should be easy enough to follow.
An answer, short and sweet
Picking up from last time, we have a Video object on the Stage with the instance name videoPlayer. We have two movie clips, also on the main timeline, with the instance names knob and track. Here’s the code, and I’ll step through what changed from last time.
var duration:Number = 0;
var ratio:Number = 0;
var id:Number = 0;
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
videoPlayer.attachVideo(ns);
ns.play("monovideo2.flv");
ns.onMetaData = function(evt:Object):Void {
duration = evt.duration;
ratio = track._width / duration;
id = setInterval(updateKnob, 50);
};
ns.onStatus = function(evt:Object):Void {
if (this.time > 0 && this.time >= (duration - 0.5)) {
trace("Video complete");
clearInterval(id);
delete this.onStatus;
}
};
function updateKnob():Void {
knob._x = track._x + ns.time * ratio;
}
knob.onPress = function():Void {
clearInterval(id);
ns.pause(true);
var vertical:Number = track._y + (track._height / 2);
this.startDrag(
true,
track._x,
vertical,
track._x + track._width,
vertical
);
}
knob.onRelease = function():Void {
this.stopDrag();
ns.seek((this._x - track._x) / ratio);
ns.pause(false);
id = setInterval(updateKnob, 50);
}
knob.onReleaseOutside = knob.onRelease;
How it works
From line 1 (var duration:Number = 0;) through the NetStream.onStatus event handler (ns.onStatus …) only one change has occurred. In the original, the function reference in the setInterval() loop was spelled out in over three lines, right there in the first parameter slot (before the comma and the 50):
…
id = setInterval(
function ():Void {
knob._x = track._x + ns.time * ratio;
}, 50
);
…
In the updated version, the function is now a named function — the custom updateKnob() — that appears immediately below the onStatus handler. Why move to a named function approach? The answer is simply ease of use. In the new version, the concept of positioning the knob repeatedly occurs twice, so rather than type out the same function literal two times, I’ve chosen to give the function its own definition and call that instead. Using a named function here makes it easier to update this code in the future, because you’ll only have to change the code in one place. Note that the updateKnob() function is virtually identical to its previous incarnation.
So far, then, the code is the same as last time, speaking from a practical standpoint. Here’s where the change happens.
The knob movie clip gets three event handlers of its own: Button.onPress, Button.onRelease, and Button.onReleaseOutside. This is typical of a drag-and-drop approach in ActionScript 2.0. Pressing starts a drag, and the other two stop the drag. In this case, there’s a bit more to it, though. The first thing the onPress handler does is to stop the setInterval() loop: the repositioning of knob every 50 milliseconds should come to a halt, so as not interfere with the dragging. Next, the NetStream.pause() method is invoked on the ns instance, pausing the video. A temporary variable, vertical, is set to the position of track plus half its height, which essentially means the vertical center of the track movie clip. Why? Well, we’re going to use that value twice, so like the declaration of the updateKnob() function, this variable saves us a bit of typing. Finally, the MovieClip.startDrag() method is invoked on the knob instance — here, the global this property refers to knob — and five optional parameters are passed in. The first means that dragging will snap knob’s registration point to the mouse. The rest indicate an arbitrary bounding box in which knob’s dragging should occur. The left-most boundary should be track’s _x position. The top-most should be halfway down the track’s vertical area, a value we just stored in the vertical variable. The right-most should be track’s right edge, described the by expression track._x + track._width, and finally, the bottom-most should be the same as the top-most.
When the user lets go … that’s when the rubber hits the road. First, dragging is stopped, by virtue of the MovieClip.stopDrag() method. Next, the NetStream.seek() method is invoked on the ns instance, with the expression (this._x - track._x) / ratio — the reverse of the forumula used to determine where to position knob in the setInterval() loop — fed in as the parameter. The video is again set in motion (ns.pause(false)), and finally, the setInterval() loop is reconvened. This is where the custom adjustKnob() function comes in handy. Note that id, again, is set to the return value of the call to setInterval(), which allows the looping to be stopped again, if need be, either by the end of the video or another drag from the user.
Because the dragging is constrained, it’s possible the user may press over knob, but release outside of it. To cover that possibility, the Button.onReleaseOutside event is handled identically to onRelease, simply by setting its function to the same one associated with the other.
Keep in mind
FLV files downloaded progressively, as in this example, can’t be sent to video keyframes that haven’t yet loaded. This means the scrubber doesn’t work fully until all of the FLV has been cached on the user’s hard drive. The above example won’t break if the user drags to a position that corresponds to a location on the video that hasn’t yet loaded — the knob will simply snap back into being animated again along the track — but be aware of the limitation. You may want to use a preloading technique to disable knob until loading is complete.
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (3) |
Permalink
|
Trackbacks (0)
|
Digg This
How to Build a Flash Video (FLV) Progress Bar (Part 1)
Posted Thursday, July 05, 2007 7:04:55 AM by David Stiller
Following on the heels, at least conceptually, of “How to Control Video (FLV) without a Component” here’s a quick look at how to indicate the progression of an FLV by way of a custom made progress bar (thanks for the suggestion, Rick!). In a follow-up article, I’ll show how to make the progress bar interactive by having the draggable knob seek to keyframes in the FLV. It turns out that much of the code for this first part derives from “How to Determine the Completion of a Flash Video (FLV) File,” which shows how to determine video length, with and without the use of Components, in ActionScript 2.0. In this article, we’ll be going the non-Component route, because FLVPlayback already has a progress bar. Before we delve into the code, we need to prepare two small movie clips.
Creating the progress bar itself
The artwork can get as pretty as you like, but for illustrative purposes, all you need for the progress bar’s track is a rectangle. Mine happens to be 12 x 180. Draw the rectangle and convert it to a movie clip, making sure the registration point is in the upper left corner. Give it the instance name track. For the knob, draw a smallish circle or almond shape. My circle is 15 x 15. Convert it to a movie clip, making sure the registration point is in the center, and give it the instance name knob. These can be on separate layers or the same, it doesn’t matter; just make sure the knob is above the track and the registration points are set as described. Position the knob at the left edge of the track.
I’ve you’ve been reading the other video-related articles on this blog, you’ll already be familiar with the non-Component display of FLVs. If not, you may want to give a quick read through the previous material. In addition to the two movie clips that comprise the progress bar, you’ll also need a Video object on the Stage. In this example, we’ll use the instance name videoPlayer.
An answer, short and sweet
Here’s the ActionScript, and we’ll step through it afterward.
var duration:Number = 0;
var ratio:Number = 0;
var id:Number = 0;
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
videoPlayer.attachVideo(ns);
ns.play("externalVideo.flv");
ns.onMetaData = function(evt:Object):Void {
duration = evt.duration;
ratio = track._width / duration;
id = setInterval(
function ():Void {
knob._x = track._x + ns.time * ratio;
}, 50
);
};
ns.onStatus = function(evt:Object):Void {
if (this.time > 0 && this.time >= (duration - 0.5)) {
trace("Video complete");
clearInterval(id);
delete this.onStatus;
}
};
How it works
The first three variables, duration, ratio, and id, prepare the way for three values used later in the code. The duration value is later determined in a NetStream.onMetaData event handler as described in the article on determining video length. The ratio value — this is the new part — is also set in the same event handler. id is used to track a setInterval() timer loop, which is also introduced in the event handler. The zeroes, for now, simply give these numbers a default value.
The next block (five lines beginning with var nc) prepares the Video object for play and loads an external FLV file. This block of code was originally explained in “How to Load External Video (FLV).”
Now comes the brains of it.
ns.onMetaData = function(evt:Object):Void {
duration = evt.duration;
ratio = track._width / duration;
id = setInterval(
function ():Void {
knob._x = track._x + ns.time * ratio;
}, 50
);
};
As recounted elsewhere on this blog, the onMetaData event is dispatched as an FLV file begins to play. Depending on how a video file is converted to FLV, it may be given a handful of extra descriptive information, including the video’s duration. In the above code, this information gets a free ride in via the arbitrarily named parameter evt. This incoming object carries with it a duration property that is: a) passed to the previously declared duration variable and b) used to determine a ratio between the width of the track movie clip and the length of the video. Thanks to this ratio, the knob movie clip can be sent to any location between the left and right edges of the track movie clip in correspondence with how much of the video has been played. Let’s see how that works.
The id variable is simply a value that keeps track of setInterval() loops. The setInterval() function returns a value, much like the Math.round() method. With Math.round(), you feed in a number, and the value you get back is the nearest integer. With setInterval(), you feed in a) a function to perform and b) in interval in which to perform it. The function gives back a number that says, “Okay, this is the identifier for the particular loop you just started.” And what function have we fed in? In this case, we’re setting the MovieClip._x property of the knob instance to the horizontal position of track plus the result of the video’s current location (the NetStream.time property of the ns instance) multiplied by the ratio variable. This is performed every 50 milliseconds once the video begins.
To save on processor cycles, the looping should stop when the video ends, so the final block of code uses clearInterval(), with id as a parameter, to do just that. This happens in response to a NetStream.onStatus event that checks if the video’s progression is both past zero and equal to or greater than a half second shy of the duration value.
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (3) |
Permalink
|
Trackbacks (0)
|
Digg This
Making Buttons Work in Flash CS3 (ActionScript 3.0)
Posted Wednesday, June 20, 2007 7:08:55 PM by David Stiller
At the time of this writing, Flash CS3 is still brand spankin’ new on the shelves. For some lucky folks, whose companies presumably have volume discounts with Adobe, the latest version of Flash is already in their hands — has, in fact, already been installed without any fanfare or training. Some of these designer/developers are finding, quite suddenly, that button symbols no longer seem to work in Flash CS3 (I’ve seen quite a few panic posts already on the Adobe forums). What gives? Is Flash broken? Not a bit of it! :) Let’s see what’s going on.
ActionScript 3.0 is a new language
The truth of the matter is, ActionScript 3.0 is different, in many respects, from AS2 or 1. (As it happens, it’s also the same in many respects, which can be a source of frustration for experienced users, but chin up!) One of the most basic, familiar things people do in Flash is to assign some ActionScript to a button. In former versions of ActionScript, this could be done in a number of ways, as explained a bit in “Museum Pieces: on() and onClipEvent().” In AS3, the rules have changed. There were at least four ways to handle events in the past — on() and onClipEvent(), dot notation, addListener(), and addEventListener() — and AS3 mercifully reduces those four down to one consistent approach. Honestly, this makes it easier.
Here’s how it goes. Let’s say you have a button symbol on the Stage. Select it, give it an instance name in the Property inspector. Now that it has an instance name, it has become accessible to ActionScript, which now has a unique way of identifying it from any other objects present. In a keyframe script (select a keyframe in line with the button, preferably a keyframe on its own layer), type the following:
myButton.addEventListener(
MouseEvent.MOUSE_UP,
function(evt:MouseEvent):void {
trace("I've been clicked!");
}
);
And that’s it. Why not select the button itself? What’s wrong with good old on()? For better or worse, direct attachment of code is a thing of the past. ActionScript 3.0 simply doesn’t support it. In fact, you’ll notice that the Behaviors panel is dimmed when a FLA’s Publish Settings are configured for AS3. Why? Because Behaviors rely on on() or onClipEvent(). Change your Publish Settings to AS2 or 1, they come back.
In the above short sample code, myButton represents whatever instance name you chose for your button symbol. If you actually used myButton, you’re good; otherwise, change the above code to match what you chose.
The classes that define button and movie clip symbols both inherit much of their functionality from a class called EventDispatcher, which provides that addEventListener() method. This method is what “wires up” such objects to respond to events, such as a “mouse up” occurrence, where the user has clicked, then released, the mouse. There are two required parameters (more, if you’re interested — see the EventDispatcher class entry for details), and they are this: a) what event to listen for, and b) what function to perform when the event occurs.
In this case, we’re listening for MouseEvent.MOUSE_UP. To see what other events are available, look up the MouseEvent class (or the Event class itself, which has many inheritors of its base functionality). The function inside any event handler is going to receive an object of its own (here, a MouseEvent object) that gets passed in as a parameter. In the above sample, that parameter is the arbitrarily named evt (for “event”), and that object contains a number of useful properties, including, for example, target, which refers back to the object that dispatched it.
Change that trace() statement from "I've been clicked!" to this, for example:
trace(evt.target);
… and you’ll see a reference to the button itself. The SimpleButton class defines button symbols in AS3, so look up that class to see what further properties are available. You could trace the button’s instance name, for example, by using this expression:
trace(evt.target.name);
… which makes sense if you consider what the expression means. Again, when the user clicked the button and released, a MouseEvent.MOUSE_UP event was dispatched. When that occurred, that dispatch included a MouseEvent instance as carry-on luggage. Because of our event handler, a function received that instance (and its luggage) by way of an evt parameter. That evt parameter is the incoming MouseEvent instance, and according to the MouseEvent documentation — make sure to click the “Show Inherited Public Properties” hyperlink under the Public Properties heading — MouseEvent instances have a target property, which points to the object that dispatched the event. Because that object was a button symbol (an instance of the SimpleButton class), we know that any reference to it has a name property.
This differs from the way such event handling was done in AS2. For button symbols, it went like this:
myButton.onRelease = function():Void {
trace("I've been clicked!");
}
Notice the lack of an incoming parameter. To refer to the button itself, from inside that function, you could use the global this property:
myButton.onRelease = function():Void {
trace(this._name);
}
In ActionScript 2.0, the property that points to a button’s instance name is _name (with an underscore). Same principle, different approach.
Enjoy ’em both
If the new approach flies over your head, just go to File > Publish Settings, select the Flash tab, and change the version of ActionScript back to AS2 or 1. But I encourage you to at least take a few stabs at the new way. As the months go by, you’re going to see plenty of AS3 stuff on the horizon. Fortunately, Flash CS lets you take your pick of the language desired.
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (34) |
Permalink
|
Trackbacks (0)
|
Digg This
Mind Your ints and uints
Posted Friday, June 08, 2007 3:37:49 AM by David Stiller
ActionScript 3.0 introduces new data types galore, and two of the funniest looking are easily int and uint. For one, they belong to an ultra-elite group whose names are fully lowercase (the third is void). For two … well, I mean … uint. Come on. ;)
What are these data types, and what are they good for? Let’s take a look.
The words and numbers
The words themselves are abbreviations of “integer” and “unsigned integer,” so that’s at least a start. Contrasted with the familiar Number data type, which can be an integer or fractional number, like 6.26, int can only be an integer. What about uint, then? What does the unsigned part mean? This gets a little interesting, actually.
Technically, the Number data type is an “IEEE-754 double-precision floating-point number” (see the ActionScript 3.0 Language and Components Reference’s Number entry for full detail).
A number typed as Number can take up as much as 53 bits of memory (over 6.5 bytes), ranging all the way from 1.79e+308 down to 5e-324. To put this in perspective, one million — a number which, in dollar bills, would make any of us happy — is 1e+6. That means 1.79e+308 is a 1 with 308 digits after it, most of which are zeros. This is an insanely huge range! It effortlessly blows away the measly six zeroes of a million.
On the other hand, int is a 32-bit number (only 4 bytes), ranging from 2,147,483,647 down to -2,147,483,648. That’s a range of over 4 billion positive and negative integers, which seems plenty good to me. In all my years of working with Flash, I haven’t yet asked it to count to two billion in either direction. If you’re doing a lot of number crunching in AS3, you can save a bit of memory by using ints instead of Numbers, if integers are all you need.
So … unsigned integers. The word “sign” in this context refers to the implied “+” in front of positive integers or the “-” in front of negative ones. Unsigned integers don’t have a sign, and in Flash that means they’re positive — always. uint numbers range from 0 to 4,294,967,295 — the same range as ints, just shoved completely into the positive half of the number line. When might you use a uint in Flash? Well, any time you want to shave bits off your number … but only for integers, and specifically only for positive integers.
A “gotcha”
A friend of mine, Rothrock, recently pointed out an interesting quality of uints that he noted on the Adobe support forums. Here’s a quick illustration via code:
var n:uint = 0;
trace(n);
What would you expect to see in the Output panel? Zero? You betcha. The variable n, typed as a uint, is set to 0, and 0 it is. Now let’s subtract 1:
n -= 1;
trace(n);
What will the Output panel show this time? Negative one? No way! uints can’t be negative. What you get is 4294967295, which means the imaginary pointer has jumped from the left edge of the uint number line to the right edge.
Why is this good to know? Well, if you happen to be using a uint in a for loop, and you happen to be counting down rather than up …
for (var i:uint = 0; i > -10; i--) {
// code here
}
… that i > -10 expression will never evaluate to false. i will always be greater than -10, so this for loop will go on looping forever.
The moral of the story? Don’t use uints to count backwards — unless you want to be counting for a very long time. ;)
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (0) |
Permalink
|
Trackbacks (0)
|
Digg This
Using the Debugger Panel to Sleuth
Posted Sunday, June 03, 2007 11:14:47 PM by David Stiller
Not long ago, I answered a forum question at Community MX where the solution arrived entirely because I used the Debugger panel to find what I needed. The developer’s issue took all of ten seconds to pinpoint, but it solved a real need. It couldn’t have been easier, either, so I’ll share what I did, hoping it helps someone else just as quickly.
The need was this: the developer was using the MediaPlayback Component (a precursor to the FLVPlayback Component) and wanted to disable a tiny, built-in triangle button that toggles a zooming/fullscreen-view of the FLV. The Component Inspector panel shows no parameter to configure this button, and it doesn’t appear anywhere in the Components Language Reference. What to do? Debugger panel to the rescue.

After having dragged an instance of MediaPlayback to the Stage and pointing it at an FLV, I used Debug > Debug Movie to run the SWF in the Debugger panel (the menu location in Flash 8 was Control > Debug Movie). When a SWF opens in cahoots with the Debugger panel, you have to click the big green arrow button to get everything started — don’t worry, you can’t miss it — and then all sorts of behind-the-scenes things come to light.
In this case, I set my gaze on the left side, which showed me the dozen or so nested movie clips that comprise an instance of MediaPlayback. One, in particular, caught my attention (yup, the highlighted one). I clicked the triangle arrow and saw that path reference change from what it was to _level0.instance1._chrome._toggleNE._minimize. Bingo!

I knew from experience that “instance1” is the first in a pattern of automatic instance names Flash will give objects without instance names. I knew I could change that to any old arbitrary instance name — and that would have been visible in the Debugger panel too, by the way — so I suggested to the developer that he type the following into the Actions panel:
instanceName._chrome._toggleNE._maximize.enabled = false;
… where instanceName should be replaced by the actual instance name of the MediaPlayback Component. And that did it. :D So what’s that enabled part? That’s a property of the MovieClip class, and it disables event handling for that clip. In fact, if desired, two lines would both disable and hade the button:
instanceName._chrome._toggleNE._maximize.enabled = false;
instanceName._chrome._toggleNE._maximize._visible = false;
Now … truth be hold, not many folks use the Media Components anymore. This isn’t a blog entry that will help countless readers with that particular Component, but that isn’t my aim. My aim is to show that the Debugger panel can be used to discover the inner workings of Macromedia/Adobe objects in addition to troubleshooting your own work. Hope that comes in handy for you! :)
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (1) |
Permalink
|
Trackbacks (0)
|
Digg This
How to Jump Randomly to Frame Labels without Repeats
Posted Wednesday, May 30, 2007 8:30:25 AM by David Stiller
One of the more popular entries of this blog describes How to Jump to a Random Frame Label. The ActionScript 2.0 involved is very straightforward, weighing in at a mere 5 lines. Its sole purpose is to choose a random label once at the beginning, then go to it (then stop). In the Comments section, a visitor named Heather asked for a variation in which the movie starts at a random label, then proceeds to the remaining labels in order, looping around to the beginning, if necessary, to hit each label once. I offered some suggested code, and eventually a number of other visitors asked for yet another variation: how to jump randomly to a whole series of labels — without repeats. That takes a bit more code, but it’s certainly doable. Let’s take a look.
An answer, short and sweet
This bulk of this code goes in frame 1, then one of its functions gets called at the end of each span of frames represented by a label. Here’s the code for frame 1:
function shuffle(arr:Array):Void {
var len:Number = arr.length - 1;
for (var i:Number = len; i >= 0; i--) {
var p:Number = Math.floor(Math.random() * (i + 1));
var t:Object = arr[i];
arr[i] = arr[p];
arr[p] = t;
}
}
var labels:Array = ["a", "b", "c", "d", "e"];
shuffle(labels);
var currentLabel:Number = 0;
function gotoNextLabel():Void {
if (currentLabel < labels.length) {
gotoAndPlay(labels[currentLabel]);
currentLabel++;
} else {
stop();
}
}
gotoNextLabel();
Gulp! That’s a lot of code, huh? We’ll step through it in the “How it works” section, but for the time being, just know that the labels array holds your frame labels (here, “a”, “b”, “c”, and so on — but you’ll use meaningful labels) and that you’ll obviously need corresponding frame labels in the timeline that holds this ActionScript. If your equivalent of label “a” spans from frames 2 through 100, you’ll put a new keyframe in your scripts layer at frame 100 with the following small function call in it:
gotoNextLabel();
If your equivalent of label “b” follows, spanning from 101 to 150, you’ll put a new keyframe in your scripts layer at frame 150 and call that gotoNextLabel() function again. Do this at the end of each span. The end result is that the playhead will visit each and every span at random without repeats.
How it works
The ActionScript above is visually organized into three sections, just for clarity. The first section (the custom shuffle() function) isn’t my own code, but a time-tested algorithm made popular on the Adobe forums by long-time contributor kglad. There are a number of variations on it, and a complete discussion would probably make a good blog entry of its own, but for the time being, let the shuffle() function be a magic stone in your pocket: it shuffles whatever array is passed to it, and it works.
The second section is comprised of two lines:
var labels:Array = ["a", "b", "c", "d", "e"];
shuffle(labels);
In this variation on the “jump to a random frame” theme, the labels array is declared outside of any function, which makes it available to all code in this timeline. It’s pretty clear to see what these two lines do. The first declares an Array instance named labels and sets it to a series of arbitrary frame labels. The second shuffles that array. After shuffle() is called, the array might look like any one of the following sample shufflings …
b,e,a,d,c
a,e,b,c,d
b,c,e,d,a
d,c,a,e,b
e,a,c,d,b
… which is great, because that means the final section of code is pretty easy. First, an arbitrarily named variable, currentLabel, is declared and set to zero.
var currentLabel:Number = 0;
Why zero? Because arrays start their counting at zero rather than one. We’re going to be starting at the first element in the array, sending the playhead to that frame label, then stepping through the remaining array elements in turn. This is accomplished by a custom gotoNextLabel() function.
function gotoNextLabel():Void {
if (currentLabel < labels.length) {
So far, the currentLabel variable (currently 0) is checked against the Array.length property of the labels instance. Have we reached the end of the array? Not yet, so the following occurs:
gotoAndPlay(labels[currentLabel]);
currentLabel++;
The playhead is sent to the frame label represented by labels[0] (the first element), and currentLabel is incremented by one (the ++ operator). This will happen every time the gotoNextLabel() function is called, and eventually, the value of currentLabel will no longer be smaller than the value of labels.length. When that happens …
} else {
stop();
}
}
The playhead stops. All spans of the timeline will have been visited, and the movie will rest comfortable in the final frame of its final randomly chosen span. To start the whole thing off, this last line of code calls the very function just described:
gotoNextLabel();
As noted earlier, you’ll have to repeat this gotoNextLabel() call in the last frame of each span of frame labels.
Have fun with it!
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (5) |
Permalink
|
Trackbacks (0)
|
Digg This
Falling Off the Face of the Earth--Into Orbit
Posted Friday, May 25, 2007 10:33:06 PM by David Stiller
When the concept of orbit was explained to me—this was many, many moons ago, in Canadian grade school—I was riveted. The act of orbiting Earth was, in fact, the act of falling … of falling at such a rate and angle that the falling was continuous. You didn’t ever land, because your trajectory was far enough that the planet’s curvature bent away beneath you.
How does this relate to me today? Well, the phrase, “fallen off the face of the Earth” generally means a person has fallen out of touch, and that definitely describes my blog activity this month. I regret that. I’ve received quite a few emails asking if everything is all right (it is!), if I’ve decided to hang up my blogging hat (no way!), and so on. So that explains the orbit business, because even if I’ve fallen off, I’m still around. ;)
Not long ago, I mentioned with glee that Foundation Flash CS3 for Designers is complete, and wow, that was a naïve misstatement! The actual writing is done, yes, but then Tom and I went through the author review process, where copyeditors tidied up our Word documents. Currently, we’re going through PDF reviews, which is exciting, because I get to see how the pages will look when they’re actually printed. The downside is, all of this takes time. I’m looking forward to free evenings more than I have the energy to express. Those free evenings are almost here! When they are, I’ll be right back in the thick of things. Thanks, sincerely, to everyone who has checked in on me.
Flash CS3 is in the stores now, and it’s great. It’s bringing up all sorts of new questions on the forums, and I’m excited about the continued interest in an application I use practically every day of my life. I’ve got a backlog of blog entries, and I’ll be back soon.
Category tags: On the Personal Side
Posted by David Stiller
Add comment |
View comments (0) |
Permalink
|
Trackbacks (0)
|
Digg This
How to Pan the Audio in an FLVPlayback Video
Posted Tuesday, May 01, 2007 4:58:27 PM by David Stiller
This one came to me in a flash (ha ha … Flash!), thanks to a friendly discussion I had the other day with site visitor Michael Lokner. He was wondering if it was possible to pan the audio portion of an FLV file in cases where the video is played in an instance of the FLVPlayback Component. In another recent article, I explained how to use the MovieClip.attachAudio() method to control NetStream-based video, but that’s a different ball of wax. The FLVPlayback Component has its own volume property, and even skins that feature a volume slider, but what about panning? After bouncing ideas back and forth, Michael and I arrived at a simple answer.
An answer, short and sweet
On his own, Michael had arrived at a respectable workaround, which was to create a Sound instance associated with the main timeline (accomplished by omitting any movie clip reference when constructing the instance). By setting up the Sound instance to control the whole movie, any panning would naturally affect the video’s audio track. The only shortcoming is that the panning would also affect all other audio in the movie. How to associate this panning with the FLVPlayback instance only?
The answer turned out to be effortless. As it turns out, all ActionScript 2.0 Components, if they have a UI, are ultimately instances of the MovieClip class. Look up any one of them in the Components Language Reference and you’ll see that it extends MovieClip. What this means, of course, is that you can use the FLVPlayback Component itself as the parameter when creating a Sound instance. Assuming an FLVPlayback instance name of videoPlayer:
var videoSound:Sound = new Sound(videoPlayer);
videoSound.setPan(-100) // hard left
videoSound.setPan(100) // hard right
How it works
Even though Components are very sophisticated objects, with lengthy inheritance chains, in the end, they are what they are: movie clips. Sound objects associated with a movie clip control that movie clip’s audio.
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (0) |
Permalink
|
Trackbacks (0)
|
Digg This
Two-Book Milestone, Around the Bend
Posted Thursday, April 26, 2007 7:56:31 PM by David Stiller
An alternate title for this entry could easily be “Why my blogging has slowed down lately,” and the shortest answer would be a muffled “busy” — muffled like a voice struggling out from beneath a heavy pile of desktop rubble — but that’s no fun, because it’s a punch line without a story. ;) It’s been nearly a year since I pulled away from an agreeable salaried position to see if I could make it on my own. So far, so good; honestly. June 7 will be the anniversary, and I’m kind of excited about it.
In an open-jawed, stunned sort of way, I’m grateful. Grateful to my wife and daughter, who have been waiting patiently for me, sometimes with a surprise pancake dinner. Grateful to friends who’ve been hanging in there, because my evenings have been shot for time out of mind. It’s all about to return to normal.
Why? Two Flash books are on the way.
I owe a lot, both in support and inspiration, to my colleagues at Community MX and to my friends Chris Georgenes and Branden Hall, who continue to send me work in addition to my usual clientele. I also owe a lot to the varied and interesting people who email me or leave comments on my personal blog, because all these reminders of Flash keep me focused.
I’m just about ready to heave a milestone over my shoulder, more or less by June. In the next few months, there will be two new Flash books in stores with my name somewhere between the endpapers. I can’t think of a better way to round out my first year as an independent contractor!
One book belongs to Chris Georgenes, who is currently finishing up his How to Cheat in Adobe Flash CS3 for Focal Press. Chris has a fantastic style all his own, and has more tips on animation — truly top notch stuff! — than anyone I know. He asked me to contribute a chapter to his book on interactivity, and I count that a privilege.
The other book belongs to Tom and Jerry. That’s the joke, anyway. ;) Tom Green, who has already written half a dozen books on Adobe products, asked me to fully co-author Foundation Flash CS3 for Designers with him for friends of ED. (I was born in Germany, so that makes me the “Jerry”; and yes, Tom really is the big gray pussycat.) We’ve been grinding away on this project since, heck, it’s been about six months. What started as a trickle has roared into a crazy-fun (but challenging!) wild water rapids expedition — which explains my recent temporary drop in blog entries.
We’ll be wrapping up soon, and the fun will really begin.
Category tags: On the Personal Side
Posted by David Stiller
Add comment |
View comments (0) |
Permalink
|
Trackbacks (1)
|
Digg This
How to Adjust the Audio Portion of Flash Video
Posted Wednesday, April 18, 2007 12:15:36 AM by David Stiller
If you’re not using the FLVPlayback Component, or one of the older Media Components, then the audio portion of video files may have you scratching your head. The Components have their own volume sliders, which makes volume control a snap, but what about panning (left to right fading), or what if you’re not using Components for video? In ActionScript 2.0, video sound is a bit … well, it’s a bit odd, but one you understand it, audio control isn’t hard.
An answer, short and sweet
In Understanding the Sound Constructor, I went into the usefulness of associating Sound instances with movie clips. To control the audio portion of FLVs, it’s just a bit more of the same. First, we’ll start with the basic “recipe” for bringing video into a Video object:
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
videoPlayer.attachVideo(ns);
ns.play("myExternalVideo.flv");
This is the block of code used in How to Load External Video (FLV) and brings the specified FLV file into a Video object with the instance name videoPlayer. Invoking NetStream methods on the ns instance (such as NetStream.pause()) controls the visual portion, but what’s missing is sound. Here’s how to do it. After the opening block of code, type the following:
this.createEmptyMovieClip("videoAudioContainer", this.getNextHighestDepth());
videoAudioContainer.attachAudio(ns);
var videoVolume:Sound = new Sound(videoAudioContainer);
videoVolume.setVolume(50);
How it works
Four lines; two things going on.
First, the MovieClip.createEmptyMovieClip() method is invoked on the global this property, which refers to the main timeline if you’re typing this code into a main timeline keyframe. This dynamically creates a new MovieClip instance at the next highest available depth, with the instance name videoAudioContainer. The instance name doesn’t especially matter; just keep in mind, this is a movie clip “container” made just for your video’s audio portion. If you wanted to, you could skip this step and put your own empty movie clip on the Stage. Just make sure it has an instance name. On this new instance, the MovieClip.attachAudio() method associates the NetStream instance ns with this movie clip.
Second, a new Sound instance, videoVolume, is instantiated and associated — this is the important part! — is associated with the videoAudioContainer clip that is associated with the NetStream instance. All in the house that Jack built. From there, the Sound instance affects the movie clip which, in turn, affects the audio portion of the video. Set the volume, as shown, or pan.
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (1) |
Permalink
|
Trackbacks (0)
|
Digg This
How to Play Sound Files Sequentially
Posted Friday, April 13, 2007 7:44:25 AM by David Stiller
Many people use Flash to play background music on their site. It’s a good use for Flash, especially if the audio is loaded from external MP3s, which keeps the SWF file size low, and if you give your visitors a way to toggle off the sound. But one song may not be enough. You may want to play a list of files one after the other. If so, the next question is, “How easy is that?” The answer is, “Very.” Let’s take a look.
An answer, short and sweet
The “trick” here — and it’s really no trick at all — is to use an Array instance to store your list of audio files, a variable to keep track of which song is current, and the Sound.onSoundComplete event to trigger each new sound. Type the following ActionScript into a keyframe:
var listOfFiles:Array = new Array("frog.mp3", "loon.mp3", "horse.mp3");
var currentFile:Number = 0;
var audio:Sound = new Sound();
audio.loadSound(listOfFiles[currentFile], true);
audio.onSoundComplete = function():Void {
currentFile++;
if (currentFile < listOfFiles.length) {
audio.loadSound(listOfFiles[currentFile], true);
}
}
How it works
The first variable, listOfFiles, points to a new Array instance that holds three elements, which are the names of three MP3 files. We could have populated this array in a series of lines, like this …
var listOfFiles:Array = new Array();
listOfFiles.push("frog.mp3");
listOfFiles.push("loon.mp3");
listOfFiles.push("horse.mp3");
… but in short sequences, the single-line approach takes less effort to type.
The second variable, currentFile, is set to zero and represents the first sound to play (arrays start counting at zero, rather than one). Finally, a third variable, audio, is declared and set to an instance of the Sound class.
To get things started, the Sound.loadSound() method is immediately invoked on the audio instance, and two parameters are provided. The first parameter is the expression listOfFiles[currentFile], which in this case resolves to the string "frog.mp3" (remember currentFile is zero, which retrieves the first element of the listOfFiles array). The second parameter tells Flash to play the file by progressive download, which means the audio will start before the MP3 has fully loaded.
On its own, the code so far would play the first song and then stop when the audio was complete. The last little bit achieves the original goal, which is to play files sequentially. When the first song (or narration, or whatever you’re presenting) is complete, the Sound.complete event is dispatched. Here, we’re writing a function to be performed in response to that event. The first thing that happens is that the currentFile variable is incremented by one, thanks to the ++ operator. So now its value is one. Next, an if statement checks of currentFile’s value is less than the total number of elements inside the listOfFiles array, thanks to the Array.length property for that instance. There are three elements in the array, and one is less than three, so the final line is executed.
Notice that the last line of code duplicates exactly what we’ve already discussed. The difference is that, this time, the value if currentFile is different. When this second song ends, the complete event will fire again, which means this function will again be triggered. currentFile will increment to two, two is less than three, and the third MP3 will play (element 2 is in the third slot, because arrays start at zero). When the third songs ends, currentFile increments to four, and because four is no longer less than three, the cycle ends.
Variation
Want to repeat the list of files when all three (or four, or however many) songs have completed? Update that last block of code like this:
audio.onSoundComplete = function():Void {
currentFile++;
if (currentFile == listOfFiles.length) {
currentFile = 0;
}
audio.loadSound(listOfFiles[currentFile], true);
} Category tags: Flash
Posted by David Stiller
Add comment |
View comments (2) |
Permalink
|
Trackbacks (0)
|
Digg This
How to Round to the Nearest Ten, Tenth, Hundred, Hundredth, Etc.
Posted Friday, April 06, 2007 12:19:48 PM by David Stiller
I was helping a friend the other day with a rounding issue. He needed to round numbers not to the nearest integer, but to the nearest hundred. So 52.3 would round to 100. 86 would round to 100 as well. 13 would round to 0 and 101.287 would round to 100. You get the idea. The Math.round() method doesn’t take any parameters except the to-be-rounded value itself, so how could this be accomplished? The answer couldn’t be simpler.
An answer, short and sweet
Basic arithmetic does it. Let’s say the original number is 52.3. To round to the nearest hundred, follow these steps:
- Divide by 100
- Round
- Multiply by 100
var num:Number = 52.3;
num /= 100;
num = Math.round(num);
num *= 100;
trace(num);
How it works
The above ActionScript could have been written out a bit longer …num = num / 100;
… but the division assignment (/=) operator reduces the required typing. They amount to the same thing (and the same goes for the multiplication assignement (*=), as well as addition and subtraction assignment operators (+= and -=).
The division/multiplication steps move the decimal place where it needs to go. The rounding functions as it always does.
Variation
If you need to round to the nearest hundredth — 189.5287 becomes 189.53 — just reverse the division and multiplication steps:
var num:Number = 52.3;
num *= 100;
num = Math.round(num);
num /= 100;
trace(num); Category tags: Flash
Posted by David Stiller
Add comment |
View comments (2) |
Permalink
|
Trackbacks (0)
|
Digg This
The VideoPlayer Class API (aka, the Missing Manual)
Posted Tuesday, February 27, 2007 7:32:16 PM by David Stiller
I was just gabbing with someone about the NetStream class, which nudged my mind toward the VideoPlayer class. According to the Components Language Reference, the FLVPlayback class “extends the MovieClip class and wraps a VideoPlayer object.” As it turns out, the VideoPlayer class is mentioned in the Components Langauge Reference, but if you dig into it, you’ll quickly discover that none of the class members are hyperlinked. In other words, you’ll get an overview of the properties, methods, and events defined by that class, but no actual explanation.
I find that an odd omission — but Adobe does make the full API available.
The URL is listed in the VideoPlayer class entry itself, but the page it brings up hides the PDF a bit. (To be fair, it may have been a direct link sometime in the past.) If you’re interested, point your browser to this whopping 112-page PDF file.
http://download.macromedia.com/pub/documentation/en/flash/fl8/VideoPlayer.pdf
It truly is the “missing manual” for this extensive API.
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (2) |
Permalink
|
Trackbacks (0)
|
Digg This
Code Hinting Regardless of Naming Conventions
Posted Wednesday, February 21, 2007 2:55:13 PM by David Stiller
Depending on my mood, I may precede certain variable names with a small prefix that describes the type of object they point to. For example, I may give a movie clip the instance name mcBall, rather than just ball. Why? Well, it allows me to see at a glance that I’m dealing with a MovieClip instance, which can come in handy during coding and also while I’m poking through the Debugger panel. It doesn’t have any measurable effect on the functionality of the variable … it’s just one of those things you get used to. I certainly don’t always adhere to this convention, but when I do, I’m practicing something called Hungarian notation, which has a decent pedigree (at least, in computer years).
Flash provides at least one naming convention that actually can make a practical difference, if you follow the suggested suffixes in the “About using suffixes to trigger code hints” section of Learning ActionScript 2.0 in Flash. I’m not especially a fan stylistically, but, for example, if I name that ball clip ball_mc, I’ll get automatic code hinting for the MovieClip class (and so will you) in ActionScript 1.0 and 2.0. A full list of suffixes is listed in that section. Code hinting is definitely a useful tool, because I’m not always familiar with the class members of the object at hand.
What if you don’t like suffixes? Or prefixes, for that matter? Well, if you use AS2’s strong typing syntax (the :Number in something like var total:Number = 5;), it doesn’t matter what you name your variable: you’ll get code hinting if you want it (see File > Preferences > ActionScript). That’s fine for everything but movie clip instance names, which aren’t necessarily declared as variables. But … see, if you declare instance names anyway — even though you don’t need to — you get the benefit of code hinting regardless of the instance name.
With a simple line like this …
var ball:MovieClip;
… even though you haven’t set that instance to anything, you’ll get MovieClip-centric code hints for subsequent references to that instance name in your code.
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (0) |
Permalink
|
Trackbacks (0)
|
Digg This
updateAfterEvent() … What’s the Scoop?
Posted Monday, February 19, 2007 9:00:09 PM by David Stiller
Someone asked me the other day, “What’s the deal with updateAfterEvent()? What, exactly, does it do, and when should it be used?” Well, I’m a fan of the ActionScript 2.0 Language Reference, so my usual reply is along the lines of, “Let’s check out what the ASLR has to say,” but in this case, the documentation doesn’t speak the whole truth.
The Scoop
First, what is this function? In reference to this question, the Language Reference correctly states that updateAfterEvent() updates the display immediately after it’s called. Normally, the display updates once per frame, so generally speaking, the faster your framerate, a) the smoother animation seems to occur and b) the more responsive certain mouse-related interactions feel. This is easiest to see, for example, in dragging or follow-the-mouse animations that don’t rely on the native MovieClip.startDrag() method. If the framerate happens to be slow, for whatever reason, such interactions can “stutter.”
Here’s a quick test. Start a new FLA and draw a quick circle. Convert it to a movie clip and give your circle an instance name; say, myClip. Set the movie’s framerate to 1fps. Yes, one frame per second. Type the following ActionScript into a frame:
this.onEnterFrame = function():Void {
ball._x = _root._xmouse;
}
Test, then drag your mouse around slowly inside the movie. The “ball” will follow the mouse horizontally, but there will be nothing smooth about its motion. Go ahead and change the framerate to the default 12fps. Test again. Still embarrassing, isn’t it?
The documentation goes on to say, still correctly, that updateAfterEvent() only works for certain Mouse and MovieClip events — and onEnterFrame isn’t one of them. So it’s no surprise that the following does not improve matters (set the framerate back to 1fps to make this painfully clear):
this.onEnterFrame = function():Void {
ball._x = _root._xmouse;
updateAfterEvent()
}
But … change onEnterFrame to onMouseMove …
this.onMouseMove = function():Void {
ball._x = _root._xmouse;
updateAfterEvent()
}
… whoa! Way cool. That’s a smooth response, and now we’re talking.
The Woops!
But wait! The documentation states that “Flash ignores calls to updateAfterEvent that are not within an onClipEvent() handler or part of a function or method passed to setInterval().” So this should only work for certain Mouse and MovieClip events, and even then, only when those are handled via onClipEvent() or a setInterval() loop. Interestingly, we’re not in an onClipEvent() handler (see the Museum Pieces article for details). Instead, we’re in the relatively newer “cousin” of onClipEvent(mouseMove), MovieClip.onMouseMove, and Flash hasn’t ignored the call to updateAfterEvent().
The Real McCoy
So … what’s the real truth? ;)
According to a handful of slow-as-molasses 1fps tests, updateAfterEvent() works under the following circumstances only:
- For the
Mouseclass: themouseDown,mouseUp,mouseMove,keyDownandkeyUpevents - For the
MovieClipclass: theonMouseMove,onMouseDown,onMouseUp,onKeyDown, andonKeyUpevents - The above pertains both to the Flash 5-era
onClipEvent()function and the newer dot notation event handling - The above also pertains both to the
setInterval()function and the “undocumented documented”setTimeout()function
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (1) |
Permalink
|
Trackbacks (0)
|
Digg This
Easy Fix to an Apparently Common FlashPaper 2 Issue
Posted Monday, January 29, 2007 8:26:11 PM by David Stiller
FlashPaper 2 was arguably, at one point, a competitor with Adobe Acrobat. I’m not suggesting this was Macromedia’s intent, back in the day — maybe it was, maybe it wasn’t — and now that Adobe owns the lot, the discussion is moot. In a nutshell, FlashPaper 2 converts documents into PDFs (just like Acrobat does, but with far fewer options), and it also converts documents into SWFs that “read” like PDFs. They can be paged, searched, printed, and so on. Neat concept, nicely executed. I wouldn’t say these SWFs have especially caught on, but that’s fine … I use FlashPaper 2 in certain cases, and because it’s so pared down, the app loads much quicker than Acrobat. That makes it an easy choice for no-frills PDF conversion.
FlashPaper 2 is available both as a stand-alone product and bundled with Studio 8. On Windows, the Studio 8 version suffers a technical issue, apparently fairly common, in that it fails when used as a printer (as in, File > Print, and choose FlashPaper 2 as the print device). Sure enough, when I re-installed Studio 8 after a recent hardware issue (completely unrelated), I could no longer create FlashPaper SWFs by printing to the app.
It didn’t take me long to find a solution, but it’s one I would never have thought to attempt. Without further ado, then, for anyone who has suffered the same fate, here it is:
- Open your Command Prompt (Start > Run… type “cmd” without quotes and click OK).
- Type cd C:\Program Files\Macromedia\FlashPaper 2\i386, then press Enter. (Note, your mileage may vary, here. Just make sure this ends up in the i386 folder of your FlashPaper 2 installation folder.)
- Type ..\fpdriversetup.exe -ui, then press Enter. This invokes the fpdriversetup.exe executable in the parent folder with the -ui switch. What it does is reinstall FlashPaper 2’s printer driver … and whatdya know, it works!
Thanks to the Adobe support forum user who goes by the name miss-n-me. Your sleuthing helped me out!
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (2) |
Permalink
|
Trackbacks (0)
|
Digg This
Sound.position "Gotcha" with Multiple Calls to Sound.loadSound()
Posted Tuesday, January 23, 2007 10:41:53 PM by David Stiller
The Sound.position property indicates how far along a Sound instance has played. If you’ve loaded an external file or attached an embedded file at runtime, but haven’t yet started it, that instance’s position property is 0. If it’s a 10-second clip and you’re 2.5 seconds in, the property reads 2500 (that’s 2,500 milliseconds). When your audio reaches its end, position will match that instance’s Sound.duration property, which indicates the total length of the audio. This is a can be useful for checking when a sound has concluded — of course, the Sound.onSoundComplete event is much more straightforward — but there are any number of reasons you might want to keep tabs on a sound’s position. Unfortunately, this property doesn’t always report the value you may expect.
The Sound.loadSound() method loads audio files (specifically MP3s) that are external to the SWF. This method takes two parameters. The first indicates the location of the MP3 file; the second is optional and determines whether or not the audio plays in stream mode. The word is a bit misleading in this context, because loaded files don’t truly stream unless served by streaming server software, such as Flash Media Server. If simply loaded from the server’s file system, the MP3 will progressively download, which means it can begin playing before the entire file has been retrieved. Comes in handy. :) The problem is, any subsequent call to loadSound() — for the same instance — leaves the position value where it was at the time the call was made. Personally, I would expect it to start again from zero, because the new file starts from the beginning (when enough of the file has loaded).
In other words, in the following code …
var song:Sound = new Sound();
song.loadSound("looneyTunesTheme.mp3", true);
… the specified MP3 starts playing as soon as enough of the file has arrived. If you monitor song.position, you’ll see it grow from zero until the end of the song. If you happen to load a new file at, say, seven seconds in …
setTimeout(function():Void {
song.loadSound("tronTheme.mp3", true);
}, 7000);
… the instance’s duration value will change — assuming each song has a different length — but its position value will keep trucking from 7000 onward.
Play this new song for several seconds, then jump back …
setTimeout(function():Void {
song.loadSound("looneyTunesTheme.mp3", true);
}, 45000);
… and position just keeps climbing. The only thing that stops it is the end of the audio. When position’s value reaches the duration value of the currently loaded file, position plumb stops updating, even if the file continues to play. Remember, this isn’t because position is actually the same as duration: because of several seconds of the other MP3 playing, the position property was thrown off.
I’m not even sure if this phenomenon is a bug or a feature, to be honest. Regardless, is there a way to “fix” it? The answer is yes.
Just before you issue a second (or third, etc.) call to loadSound(), be sure to call Sound.start() first, and pass in the optional secondsOffset parameter. That resets position.
// … existing code
song.start(0);
song.loadSound("aintNoMountainHighEnough", true); Category tags: Flash
Posted by David Stiller
Add comment |
View comments (6) |
Permalink
|
Trackbacks (0)
|
Digg This
setTimeout() "Gotcha" in Class Files
Posted Tuesday, January 16, 2007 8:27:19 AM by David Stiller
The setTimeout() function is a valid citizen in the realm of ActionScript 2.0; it was simply left off the roster for some reason, so you won’t find it in the documentation. It works very much like its JavaScript counterpart and is less cumbersome to use than setInterval() for triggering a single delayed action. You can reference setTimeout() just fine in timeline code, but I found an unexpected problem when employing this function in a class file. Its presence halted the compile process and caused all sorts of misleading errors, such as the idea that Stage can’t be reference in a class file (it certainly can). Is there a workaround? Yes.
An answer, short and sweet
If you find yourself desiring setTimeout() inside a custom class, use the array access operator to refer to the function.
_global["setTimeout"]
This one of the techniques you can use to reference objects dynamically — and even functions are objects. To actually trigger the function, you need to add the parentheses, and those come right after the closing bracket. At that point, it’s business as usual.
_global["setTimeout"](functionToTrigger, 1000);
How it works
To be honest, I can’t explain the “how” especially well, in this case. The setTimeout() function was left out of the documentation and the intrinsic class definition files, which means the compiler (sometimes) doesn’t know it exists. Why this only happens in external class files is beyond my grasp. But the solution is easy, enough. :) I had to experiment with which object to use as the prefix (I tried _root, a passed-in reference to the main timeline, and this, but suddenly _global occurred to me, and that’s what works).
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (3) |
Permalink
|
Trackbacks (0)
|
Digg This
A Tip on the Boolean() Function (Casting as Boolean)
Posted Tuesday, January 09, 2007 2:00:50 PM by David Stiller
When you load data from XML or text files, or retrieve values from the TextField.text property, the information you get is a string. Even if the incoming value is, say, the numeral 3 (without quotes), it’s a string when evaluated by ActionScript. Even if the value is “false” (with or without quotes), it’s a string — not a Boolean — and may appear to ActionScript as true! Whoa! That could cause a few problems. In the case of numbers, there’s an easy way to tell ActionScript what the datatype should be, and it’s called casting. You may cast a string numeral into an actual Number datatype by using the Number() function. With a text field whose instance name is money …
var looseChange:Number = 0;
looseChange = Number(money.text);
That converts the value of the money.text property to a true number, which you can verify with trace(typeof(looseChange)); — but the Boolean() function handles things differently.
In ActionScript, false is synonymous with 0 and true is synonymous with every other number. If you cast the number 0 as Boolean, you’ll see false in the Output panel.
var num:Number = 0;
trace(Boolean(num));
Same goes for any other number, except the output will be true.
var numA:Number = 1;
var numB:Number = 2;
var numC:Number = 1000;
trace(Boolean(numA));
trace(Boolean(numB));
trace(Boolean(numC));
But strings … those are different. Since Flash Player 7, when the Boolean() function sees a string, it counts the number of characters in that string. If the string is empty (zero characters), the cast resolves to false. A count of one or more characters resolves to true.
var strA:String = "0";
var strB:String = "1";
trace(Boolean(strA));
// outputs true, even though the string was 0
trace(Boolean(strB));
// outputs true, but not because the string was 1
Even the strings “true” and “false” both resolve to true, because they contain one or more characters.
So, is how can text values be cast as true Booleans? Well, you can either write your code to abide by the rules as they are — that is, make sure your XML file contains empty strings for false and non-empty strings for true — or use a conditional statement.
var str:String = "false";
var boo:Boolean;
if (str == "false") {
boo = false;
} else {
boo = true;
}
Or, to be more compact about it, use the conditional operator:
var str:String = "false";
var boo:Boolean = (str == "false") ? false : true ; Category tags: Flash
Posted by David Stiller
Add comment |
View comments (4) |
Permalink
|
Trackbacks (0)
|
Digg This
Simplify: Use Boolean Expressions Creatively
Posted Wednesday, January 03, 2007 8:11:18 PM by David Stiller
I was coding up a slideshow this afternoon for a quick demonstration to a client. In the end, much of today’s “rough draft” ActionScript will be converted into a custom SlideManager class. For the time being, though, my “jump in and throw something together” approach was helpful anyway, because it brought to mind a number of features the client is going to ask about — I’d bet money on it — and now I’ll be prepared. In addition, it reminded me of an admirable principle in programming: elegance.
This entry is more of a “think about it in broad terms” tip than the usual “type this ActionScript, exactly.” Here’s the situation. I had just finished writing a set of functions to advance the slideshow. They were called previous() and next(). I had already stored a number of slide objects in an array (these will eventually be instances of a Slide class). The first thing the next() function does is check if the current slide is less than the total number of slides. If it is, then the slideshow hasn’t yet reached its end, which means the “next” button can remain active. If it isn’t, then the slideshow has reached its end, and the “next” button needs to be disabled. This includes disabling any event handlers associated with it, dimming it (graying it out), and a handful of other things. At first, I handled this with an if statement. Makes sense, right?
function next():Void {
if (currentSlide < slides.length – 1) {
// still going
} else {
// reached the end; disable
}
}
The if statement checks the value of a currentSlide variable against the value of the Array.length property a particular slides array. The part at the end that substracts one is there because arrays start at zero, rather than one. In an array of three items, the array’s length is 3, but its elements run from 0 through 2.
I had already written a class called NavigationButton, which features an active property. I coded active to be similar in principle to MovieClip.enabled or Button.enabled: set it to true and the button is active; set it to false, it disables, automatically dims, and does the other things it needs to. So that if statement above could have been written like this (and, in fact, was).
function next():Void {
if (currentSlide < slides.length – 1) {
btnNext.active = true;
} else {
btnNext.active = false;
}
}
Still makes perfect sense. When the slideshow is over, deactivate the button; otherwise, leave it active. But then I saw the correlation between the true/false nature of the if statement and the true/false nature of the active property. Suddenly, I saw where I could collapse those lines into something neater, more elegant. I rewrote it like this:
function next():Void {
btnNext.active = (currentSlide < slides.length - 1);
}
See why that works? The expression currentSlide < slides.length – 1 hasn’t changed. It’s purpose is to get that if statement to make a decision, either true or false, which is all an if statement ever does anyway. That expression resolves to either true or false, and since the NavigationButton.active property takes a Boolean value, the expression can be used to actually set the property, rather than steer an if statement toward doing the same thing.
NSurveyor, who often comments on my developer blog, uses this sort of “trick” more than anyone I know, often to great effect. When it reduces the number of lines you have to type, it’s a terrific practice. Of course, it also has the potential to make code more difficult to read, especially to someone who wasn’t present when you wrote it, so weigh the pros and cons before going nuts with it. But it sure it neat to “fold” several lines into one!
Category tags: Flash
Posted by David Stiller
Add comment |
View comments (0) |
Permalink
|
Trackbacks (0)
|
Digg This
43 posts
Showing 20
| Next
(page 1 of 3)
See Community MX content by David Stiller


Blog RSS feed













