Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning ActionScript 2.0 2006

.pdf
Скачиваний:
105
Добавлен:
17.08.2013
Размер:
12.47 Mб
Скачать

Chapter 20

How It Works

You can see in this example that a raw feed has been placed into your application with just a few lines of code. Because the Camera object was placed onto the stage via the Video object, you have access to all of the Video object’s methods, including smoothing, alpha, and scaling.

Also, you can place the Video object within a movie clip and create a Bitmap object. You can then begin to manually track changes in the webcam image based on RGB pixel values of the bitmap.

Now try to use your webcam to detect motion.

Try It Out

Detect Some Motion

If you haven’t done the previous Try It Out example, you should do so now, because you’re going to add to the existing code to check for motion activity in your camera feed to fire an event.

1.Open the loadCamera.fla from your work folder.

2.Click the first frame in the timeline, open the Actions panel, and type the following ActionScript code:

var theCamFeed:Camera = Camera.get(); var myCamera:Video = holder.myCamera; myCamera.smoothing = true; myCamera.attachVideo(theCamFeed); foo = setInterval(this, “rotate”, 1); theCamFeed.setMotionLevel(20, .5);

theCamFeed.onActivity = function(active) {

trace(theCamFeed.activityLevel); if (active == true) {

trace(“motion detected”); } else {

trace(“motion stopped”);

}

};

3.Test your work. You should now see your video playing in the top-left corner of the stage. You will also see the output window appear with trace output according to the activity being detected in the camera image.

How It Works

In this example you saw how to invoke a method when the camera sends an image frame, which is significantly different from the preceding frame. The value of the change is measured as a percentage of difference from the previous frame. This is presented as a number from 0 to 100.

The other option you used was set the second parameter of the setMotionLevel method. By setting a very small number, the Camera object doesn’t wait very long to fire the onActivity method with a false parameter. The default value is two seconds. In interactive content, you might want to change this value to be larger or smaller depending on feedback.

Ready to try something a little more challenging?

518

Managing Video

Try It Out

Track a Pixel in the Webcam in Real Time

In this example you use the Bitmap object to track pixels. You’ll want to have something like a brightly colored piece of paper that is in high contrast with the rest of the field in view of the webcam. (A bright yellow note pad should work well.)

This example contains some code that is fairly advanced. The detail as to how the getRGB function works is beyond the scope of this book. Just know that it takes a hexadecimal value and returns an RGB object, which is what you need to examine the pixels and compare them. You can take this function for granted, because it’s a standard conversion.

1.Open a new FLA and save it as trackPixel.fla in your work folder.

2.Click the first frame in the timeline, open the Actions panel, and type the following ActionScript code:

var theCamFeed:Camera = Camera.get(); var myCamera:Video = holder.myCamera; myCamera.smoothing = true; theCamFeed.setMode(240, 200, 24); myCamera.attachVideo(theCamFeed); holder._xscale = 200;

holder._yscale = 200;

3.Open the Library panel. Select the menu display icon in the Library panel title bar and choose Select New Video. A Setup dialog opens; be sure to select ActionScript-Controlled. A video symbol will appear in the library. Drag an instance of the video symbol from the library to the stage.

4.In the Properties panel for the video symbol, now on the stage, change the name to myCamera. You can change the height in the properties panel to 200. Change the width to 240.

5.Click the video to be sure that it is highlighted. Select Modify Convert to Symbol and select Movie Clip. Name the symbol holder. In the Properties panel for the new movie clip, give it an instance name of holder.

6.Test your work. You should now see your video playing in the top-left corner of the stage. Close the SWF and go back to the main timeline ActionScript.

7.Draw a circle on the stage using the Ellipse tool. Color the vector to suit. Click the circle to be sure that it is highlighted. Select Modify Convert to Symbol and select Movie Clip. Name the symbol dot. This symbol will now be in the library, so delete it from the stage. Be careful not to delete the Video object and holder movie clip you created in step 5.

8.Open the Library panel. Select the Linkage option of the movie clip symbol named dot. Be sure Export for ActionScript is selected and give it an Identifier name of dot.

9.Return to the frame 1 ActionScript by highlighting frame 1 and opening the ActionScript panel. Add the following code, which sets up the bitmap copy of the camera image:

import flash.display.BitmapData; var bitmap1:BitmapData;

var image1Clip:MovieClip = this.createEmptyMovieClip(“image1”, 1); image1Clip._xscale = 200;

image1Clip._yscale = 200 image1Clip._alpha = 0;

var sprite:MovieClip = this.attachMovie(“dot”, “dot”, 2);

519

Chapter 20

bitmap1 = new BitmapData(myCamera._width, myCamera._height); image1Clip.attachBitmap(bitmap1, 1); image1Clip.useHandCursor = false;

image1Clip.onRelease = function() {

this._parent.trackPixel = bitmap1.getPixel(this._xmouse, this._ymouse); this._parent.trackPixel =

this._parent.getRGB(this._parent.trackPixel.toString(16)); };

10.Enter the following code after the code you added in step 9:

function getRGB(hex) { var obj = {};

var myColour = “0x”+hex; obj.b = myColour & 0x0000ff; myColour = myColour >> 8;

obj.g = myColour & 0x0000ff; myColour = myColour >> 8; obj.r = myColour & 0x0000ff; return obj;

}

11.Now add the code that finds and compares pixel values:

function findPixel() { bitmap1.draw(holder);

var imageWidth:Number = bitmap1.width; var imageHeight:Number = bitmap1.height;

for (var i:Number = 0; i<imageWidth; i=i+6) {

for (var j:Number = 0; j<imageHeight; j=j+6) { r = false;

g = false; b = false;

var xyColor = getRGB(bitmap1.getPixel(i, j).toString(16)); var variance = 5;

if (xyColor.r>=(trackPixel.r-variance) && xyColor.r<=(trackPixel.r+variance)) {

r = true;

}

if (xyColor.g>=(trackPixel.g-variance) && xyColor.g<=(trackPixel.g+variance)) {

g = true;

}

if (xyColor.b>=(trackPixel.b-variance) && xyColor.b<=(trackPixel.b+variance)) {

b = true;

}

if (r == true && g == true && b == true) { new mx.transitions.Tween(sprite, “_x”,

mx.transitions.easing.Back.easeOut, sprite._x, i*2, .5, true); new mx.transitions.Tween(sprite, “_y”,

mx.transitions.easing.Back.easeOut, sprite._y, j*2, .5, true); j = imageHeight;

520

Managing Video

i = imageWidth;

}

}

}

}

foo2 = setInterval(this, “findPixel”, 42);

12.Test your code. You should see your camera image in the top left of the screen. Click a uniquely colored pixel, or hold up a piece of brightly colored paper such as yellow note paper. Click the color using the mouse. The circle will now follow the color and slight variations as you move the color around the image. Try clicking different objects.

How It Works

By using the Bitmap object, you’ve begun to uncover some interesting capabilities to track webcam movement and objects beyond the native method set available in the Camera object.

The first step was to create a web camera object on the stage, which sacrificed some quality for speed. This was accomplished by setting the mode of the camera to collect only a very small image. The camera was then smoothed, while the holder clip was scaled up. This enabled you to show a decent image while keeping FPS up.

You then added a small sprite, which acts as your indicator that the script is indeed working. The next thing you did was to create a copy of the camera image by creating a second movie clip. This clip was then filled with a Bitmap object. Filling the Bitmap object runs slightly more slowly than the actual playback of the webcam, so the bitmap is placed over the existing webcam image and the bitmap’s container clip is set to alpha zero. This enables you to query the pixels via a mouse event without losing perceived performance. The mouse event is then defined. The mouse event defines the color of the pixel to be tracked.

Next the getRGB method was added. It is not important to understand the inner workings of this function at the moment. Just know that it works and that it is a standard method for extracting RGB values from hexadecimal numbers.

Finally, you added a function called by an interval. This function redraws the bitmap data from the camera image into the Bitmap object. The object is then queried in a loop to find the first instance of a pixel, which matches the RGB values of the color chosen by the user. Because the webcam color and performance can change from frame to frame, a variance value allows deviations of the color. After an instance of an acceptable pixel is found, the sprite is moved to that position, and the for loop is ended to save CPU time. Because this uses a linear left-to-right, top-to-bottom method for finding pixels, this method will always be biased to the top right, because it will stop at the first pixel that meets the requirement.

Because there are hundreds of pixels in an image, when polling a video image on-the-fly like this you must sacrifice some precision. In this case it was decided to poll only every sixth pixel. This way you only have to iterate through one-sixth of the pixels to get basically the same results. Optimization like this is key for matching performance and acceptable error.

This is, of course, just an introduction to how the Camera object can be examined. Many more efficient methods for finding pixels exist, such as radial proximity. You should think about how you could improve performance of finding pixels and come up with your own code and ideas for manipulating not only the Camera object, but the Video object as well.

521

Chapter 20

Security Pop-Up Considerations

Both the Microphone and Camera objects ask users whether they would like to allow your SWF to access these items. The onStatus methods of the Camera and Microphone objects are fired when the user inputs an answer to the pop-up. If the user agrees, the onStatus returns true. If the user declines access, onStatus returns false.

After users have allowed the microphone or camera, they will not be asked again, until the next session.

A user does not have to view this pop-up every time, however. If he goes to the Privacy Settings panel, he can permanently deny or allow access of the microphone and camera to your domain. Many times users don’t know this, and it is handy to open the Settings dialog manually and direct them on how to do this. You cannot make these settings changes with ActionScript; they can be made only by the user.

Summar y

In this chapter basic concepts about video compression and playback were presented so that you can include video within your projects with ease. Examples were given to give you complete control over video behavior and how the media can interact with the rest of your application.

The webcam was presented as an input device, with the ability to have visual changes in the webcam image enact changes with the application.

Both video and the web camera were used with the Bitmap object to manipulate the image. When the bitmapData object is combined with video and the webcam you can integrate video at a level no other technology can with such ease.

Hopefully this chapter got you thinking of using Flash Video in ways you might not have thought of.

Exercises

1.Separate the audio and video from a single MOV or AVI file. Wrap the video as an SWF file. Load the video via LoadMovie. Control the current frame of the SWF via gotoAndPlay by loading the MP3 track and using the position and duration properties to determine the current position of the SWF.

2.Using a webcam, detect movement in the webcam’s image and play an event sound.

522

21

Using ActionScript to Communicate with a Ser ver

Flash is built on the principle that the web is entertaining and useful. Usefulness on the web is what separates different types of Flash content. Some Flash exists to entertain; some exists to serve information and transact data. Flash is an animation format and a rich Internet application deployment platform. Flash becomes an application platform when the author of the Flash decides to load data from outside sources or manipulate and send data.

In this chapter you learn about data. Data is what computers are for; it’s what you look for when you move across the Internet. If you want to be something on the Web, you have to move, modify, exchange, or serve data. Flash is no exception.

Screen persistence is the capability to refresh the screen with new images and information without replacing the entire screen. Often, HTML-driven web sites must redirect to a new page or refresh the existing page entirely to reflect content changes. Screen persistence drives the interest in Ajax (Asynchronous JavaScript and XML), a concept of relying on the XMLHttpRequest object method of JavaScript to rewrite div content. The capability to transmit and receive data seamlessly within your user interface is the power Flash and Ajax offer.

External Data and Usability Concerns

External data comes with a price. Applications that run directly on the desktop don’t refresh an entire user interface to alert you of a data change. Imagine if a Word document required an entire refresh of the screen to simply recast a length of text to be bold.

A page refresh can seem jarring. However, users on the Internet have become accustomed to it, and expect it. This type of adaptive behavior becomes inherent workflow expectation. Browser users realize when the screen disappears and the hourglass starts spinning that the application is in fact working, not breaking.

Chapter 21

Flash provides freedom but exposes you to the possibility of endangering the user experience. When a user engages a Flash application, if the interface responded differently for one transaction than another, a user might perceive an application error and become confused.

These are two very different user perceptions and expectations that separate the browser experience and the Flash experience.

Data Latency: Asynchronous

Communication

A Flash user interface must be designed with a specific user workflow and task in mind. For example, when you open your favorite text editor and save a page of text, the computer reacts quickly, and the existence of the file confirms that the function was successful. During complex code operations, welldesigned applications give you progress indications when a task is being performed, such as when you save a very large text file. On the Web, delays can be amplified by network latency, which is the time it takes for data to travel over the established network connection.

A persistent Flash application is also at the mercy of server-side script runtime delays. For these situations Flash provides asynchronous event handlers. Asynchronous code is when two programs, running separate from one another, both invoke a procedure to cooperatively complete a function. Because a program can’t directly know when another program has completed its part of a function, it must wait and have code ready to intercept the results.

It is important in these situations to realize that the browser’s hourglass won’t begin spinning. Flash has nothing automated to tell users that it is processing data. A Flash user interface must show the user some indication of work being done or the amount of work left to do. The interface can also be designed so that the data transmission is invisible. Server-side scripts often can work with data from your Flash movie while sending the Flash Application an immediate answer while it continues to work.

Be smart. Understand your user workflow and user. Keep your latency and wait times as minimal as possible. Keep your user interfaces responsive to input, even when data is transacting slowly.

Using LoadVars

The LoadVars class was added to the Flash Player in version 6, and has been one of the most popular and convenient methods for importing data into an SWF file. The global functions loadVariables() and loadVariablesNum() access the same data as LoadVars, but LoadVars is still a powerful class. If you’re working with any experienced ActionScript users, you may want to read through this section; if you aren’t, you could skip it and just use the global functions.

You can use LoadVars to import raw strings and make new types of data parsers. You can use it to decode classic ampersand-delimited files. LoadVars, without intervention, expects to load ampersanddelimited value pairs. You can use it to populate form data and automatically package that data into POST and GET requests.

524

Using ActionScript to Communicate with a Server

Ampersand-Delimited Data

A delimiter is anything that comes between two things. You use delimiters to form a linear series of objects. The following strings are all delimited in a unique way:

var1&var2&var3&var4 //delimited with ampersands

var1

var2

var3

var4 //delimited with spaces

var1|var2|var3|var4 //delimited with pipes

Flash can load and parse data that is encoded in ampersand-delimited name/value pair format. The name and value in each pair are, in turn, delimited with an equal sign. The LoadVars class is capable of parsing data such as the following example:

var1=A Rock and Roll Station&var2=An oldies Station&var3=An Electronic Music Station&var4=Another Electronic Music station

Data such as the preceding example is parsed into variables with string values. For example, the preceding data can be parsed into four variables (var1, var2, var3, and var4) with string values. Flash does not natively parse such data into any other primitive or reference data type.

LoadVars Class Methods

The following table describes the methods of the LoadVars class:

Method

Return

Description

 

 

 

addRequestHeader

Nothing

Adds a request header when the XML object is

 

 

requested from the server.

getBytesLoaded

Number

Returns the byte amount of the file that has loaded

 

 

into the XML object specified.

getBytesTotal

Number

Returns the total byte size specified in the header of

 

 

the requested file.

load

Nothing

Specifies a target file to load and proceeds to load it.

decode

String

Parses data into LoadVars object properties.

send

Nothing

Sends the specified XML object as a document to a

 

 

URL.

sendAndLoad

Nothing

Sends the specified XML object as a document to a

 

 

URL and specifies a return object to place the server

 

 

reply.

toString

String

Returns a literal string of the specified XML object.

The addRequestHeader() method has two usages. Following are examples of their syntax:

Set just one header field (for example, From):

525

Chapter 21

myVars.addRequestHeader(name:String, value:String) : Void

Send an array to set multiple header fields:

myVars.addRequestHeader([name1:String, value1:String, name2:String, ;

value2:String]) : Void

Headers give the server information about the request being sent. Some requests require special headers to be recognized. Request headers are most often used to instruct the remote application about how to use incoming data. You can read more about the HTTP request headers specification at www.w3.org/Protocols/HTTP/HTRQ_Headers.html.

The getBytesLoaded() method is used to measure the progress of asynchronous data loading into the object. It has no parameters and returns the number of bytes loaded so far. Here’s its syntax:

myVars.getBytesLoaded();

It is most often used to construct a preload bar or percentage-loaded textField.

The getBytesTotal() method is most frequently used to measure the progress of asynchronous data loading into the object. It has no parameters and returns the total number of bytes yet to be loaded. Here’s its syntax:

myVars.getBytesTotal();

It is often used to construct a preload bar or percentage-loaded textField.

The load() method has one parameter, a String object defining the target path of the data file to load. load() is used when sendAndLoad is not required. Here’s the method’s syntax:

myVars.load(path:String);

decode() has one parameter, a String containing ampersand-delimited data. The method then parses the data into properties of the LoadVars object. Here’s the syntax:

myVars.decode(data:String);

The send() method encodes custom properties of the LoadVars object into ampersand-delimited format and sends them to the specified resource. It has three parameters:

A String defining the target URL (required).

A String specifying a window destination for the server response (required).

If you do not want to leave the Flash application or open a new browser window, use the sendAndLoad() method instead.

A String specifying either GET or POST (optional).

The data is sent using the HTTP POST method by default. The method’s syntax is as follows:

myVars.send(serverPath:String, windowName:String, httpMethod:String);

526

Using ActionScript to Communicate with a Server

The sendAndLoad() method also has three parameters:

A String defining the target URL (required).

A target LoadVars object (required). Unlike send(), the server response for a sendAndLoad() call is handled by a target LoadVars object that you specify with the second parameter. When a response returns, Flash calls the onData() or onLoad() method of the object specified.

A String specifying either GET or POST (optional).

Like the send() method, sendAndLoad()sends the data using HTTP POST by default. Here’s its syntax:

myXML.sendAndLoad(serverPath:String, target:LoadVars, httpMethod:String);

The toString() method can be invoked to transform the LoadVars object into a string. It has no parameters. Here’s the syntax:

myVsrs.toString();

Flash cannot create and save external files. If you must save your variables, you must use either the send() method or the sendAndLoad() method to transport the data to an external application or server method.

The LoadVars class has two properties, which are described in the following table:

Property

Type

Description

 

 

 

contentType

String

The MIME type associated with the object specified.

loaded

Boolean

Becomes true when the onLoad event has fired.

Creating a LoadVars Object

LoadVars uses a typical constructor. Here is an example, with some variables being added to the object itself:

var myVars:LoadVars = new LoadVars(); myVars.station1 = “Rock and Roll Oldies”; myVars.station2 = “Today’s hit music”; myVars.station3 = “Electronica in the Nineties”; myVars.station4 = “Electronica Monster 2”;

When you trace the myVars object directly, the output window shows a URL-encoded string:

station4=Electronica%20Monster%202&station3=Electronica%20in%20the%20Nineties&stati

on2=Today%E2%80%99s%20hit%20music&station1=Rock%20and%20Roll%20Oldies

That’s really all there is to creating a LoadVars object. This simplicity can be an important tool for rapid development of network communications in Flash. Although the preceding example merely adds a few properties to a new LoadVars object, it sets the foundation for sending and loading data to and from external resources. You can read more about loading and sending data in the following sections. First, however, complete the following Try It Out exercise.

527