Flash 3D Cheats Most Wanted

In this final technique, you'll approach the closest approximation of true three-dimensional perspective rendering yet. However, you are still very far from burdening either your processor or your user with the intricacies of full three-dimensional representation.

In this system of three-dimensional text, words are fixed in a large spatial area (see textInspace.fla ). Clicking on a word zooms the user through the space to focus on the selection. Words that move beyond the camera are replaced in the distance to create the illusion of infinite depth.

You can trick most users into believing your type exists within a third dimension using only scale and screen positioning. The closer a word is to the user, the larger it becomes. The opposite is true for words far away; they are very small. Words also appear to move faster when they are closer.

Building the Text Space

Lost in text space is a modification of a parallax system (refer to Chapter 6 for more details). It takes only a few simple equations to set the word object up ”the rest of the algorithmic work will be devoted to ways in which you can move around in this word space. The completed version of this example can be found in this chapter's source files as textInSpace.fla .

  1. Let's get busy creating the first crucial object of the system, the SpaceWord . Create a new movie clip and name it SpaceWord . Export the movie clip with the linkage ID SpaceWord . Name the first layer definition , and create two new layers called word and button (by now, this setting-up stage is probably a piece of cake for you).

  2. On the layer named word , create a dynamic text field and assign it the variable txtWord . Change the style and size of the word as you see fit. Be sure to center the text field and embed font outlines (by clicking the Character... button) for the cleanest possible presentation.

  3. On the button layer, create a rectangular button that covers an average- sized word. This button will be used to select the word and focus the camera on its position in three-dimensional space. Give this button an instance name of btnSquare . The instance name will be important later when you assign code and actions to the button.

  4. On the first frame of the definition layer, type the following to set up the foundation for your prototyped SpaceWord :

    #initclip // constructor function SpaceWord() { // set up button functionality this.btnSquare.onPress = function() { // push the camera towards the word Object.environment.cam.dx = this._parent,x; Object.environment.cam.dy = this._parent.y; Object.environment.cam.dz = this._parent.z+Object.environment.f1*.9; // disable and hide button this.enabled = false; this._visible = false; }; // set continual function to render word this.onEnterFrame = this.render; } // allow SpaceWord to inherit MovieClip properties SpaceWord.prototype = new MovieClip(); // instance methods go here... // Connect the class with the linkage ID for this movie clip Object.registerClass("spaceWord", SpaceWord); #endinitclip

  5. In the preceding code, you see right away that there is some initialization that occurs with each instance of the SpaceWord . Primarily, this sets what happens when the button of the SpaceWord is clicked. Also, you are using the onEnterFrame event to drive the behavior of the word. This includes the scaling and positioning of the text to emulate a three-dimensional environment. You'll next write the render function, as you have done before, with some slight modifications (this slots in above the class registration, as usual ”see textInSpace.fla ):

    // instance methods go here... SpaceWord.prototype.render = function() { var zActual = Object.environment.fl+this.z-Object.environment.cam.z; // has the object moved behind the camera? if (zActual>0) { // object is still visible // calculate scale var scale = Object.environment.fl/zActual; // set position using camera as an offset this._x = (this.x-Object.envirornment.cam.x)*scale; this._y = (this.y-Object.environment.cam.y)*scale; // set size this._xscale = scale*100; this._yscale = scale*100; } else { // object has moved behind camera // reposition further down the line this.z += Object.environment.f1*2; // enable button this.btnSquare.enabled = true; this.btnSquare._visible = true; } };

    Here, each word calculates the fractional influence of its z position based on the location of the camera and the focal length of the environment. This value is calculated on the first line of the function and stored as zActual . If the result is greater than zero, the object is in view of the camera. The screen position and size is calculated by the word's relative location to the camera.

    If the value is less than or equal to zero, the object has actually moved behind the camera. In this case, you want to reposition the object in the distance by twice the value of the focal length. Notice also that you are reenabling the button when you reposition it, so you can select the object again.

  6. Now you'll write two setter functions to allow you to set the attributes of the word. This includes the actual word displayed and the position of the word. The following needs to be placed just after the render function in the SpaceWord definition:

    SpaceWord.prototype.setWord = function(s) { this.txtWord = s; }; SpaceWord.prototype.setPosition = function(x, y, z) { this.x = x; this.y = y; this.z = z; };

    The SpaceWord object is now complete. However, you are not ready to test your movie because you have not defined the environment in which the words exist, nor have you developed an algorithm that creates instances of the SpaceWord . You'll do that next.

  7. First, define the environment as the root of the movie. On the first frame of the main timeline, in any layer, type the following:

    // register root as environment Object.environment = this; // create camera object this.cam = {x:0, y:0, z:500, dx:0, dy:0, dz:-500}; // set environmental constants this.fl = 1000; // a string of words related to the wind this.somewords = " wind breeze storm stormy blow gush whoosh thrash whirl push roar rush caress flow swoop "; // convert the string of words into an array of words this.wordList = new Array(); this.wordList = this.somewords.split(" ");

    The cam object holds the location ( x , y , and z ) and destination ( dx , dy , and dz ) of the camera object. Initially, the camera is center focused, deep in the space. Its destination is back 500 pixels, the effect being that immediately when the movie runs, the camera is already moving through space, pulling backward. The variable f1 represents the focal length of the three-dimensional perspective.

  8. You'll also create an empty movie clip called space in which you can place all of your SpaceWord objects. The advantage to doing it this way is that you now have a nice, tangible handle on the text space's vanishing point (0,0). In effect, the vanishing point of the text space system is set by the screen position of the space object. Here is the code that creates the space movie clip and positions it in the center of the movie's stage:

    // create 'space' to which all words will be attached this.createEmptyMovieClip("space",1); // center 'space' on the stage space. _ x=400; space._y=300;

  9. Now you can program the loop that actually creates instances of your SpaceWord . The following should be typed on the first frame of the main timeline, immediately after creating the space object:

    // create one instance for each word in the list for (n=0;n<this.wordList.length;n++) { // pick a word from the list var word = Object.environanent.wordList[n]; var x = random(800)-400; var y = random(800)-400; var z = random(Object.environment.f1*2)-Object.environment.f1; // create an instance of the SpaceWord object nombre = "word"+String(depth++); initialization = {txtword: word, x: x, y: y, z: z}; space.attachmovie("spaceWord", nombre, depth, initialization); }

  10. As one final step, you need a function at the environmental level that moves your camera. The function will execute continuously because it is assigned to the onEnterFrame event of the main timeline. This code immediately follows the preceding, on frame 1 of the main timeline:

    this.onEnterFrame = function() { // move the camera to its destination this.cam.x+=(this.cam.dx-this.cam.x)/10; this.cam.y+=(this.cam.dy-this.cam.y)/10; this.cam.z+=(this.cam.dz-this.cam.z)/30; }

    The camera moves by a speed defined within each of the preceding equations. Whenever the destination of the camera changes, the camera automatically moves toward it. For the x and y positions, the translation per frame is divided into tenths; for the z position, the translation is divided into thirtieths. Essentially, the larger the divider, the slower the camera will move into position.

Your lost in text space system is now complete. Test your movie ( textInSpace.fla ) and you should immediately see words streaming into the background. Select a word and you should be drawn through the space, focusing slowly on your selection:

If everything is coming together, you are now flying through space. If you can pull yourself away from clicking around these new planetary text objects, you can continue to develop this system and make it even more interesting.

Free-Floating Words

As a potentially interesting exercise, you might allow your words to move themselves . These modifications exist in a file called textInSpace_floating.fla . For the sake of simplicity, you will allow words to move only along their x- and y-axes. You need only extend the current functionality of the SpaceWord prototype to include a function called float (positioned just after the render function's definition):

SpaceWord.prototype.float = function() { // float about the space randomly // apply random forces to velocities this.vx += (random(101) - 50) / 500; this.vy += (random(101) - 50) / 500; // add velocities to position this.x += this.vx; this.y += this.vy; // bound check if (this.x<-400) { this.x=-400; this.vx*=-.85; } else if (this.x>400) { this.x=400; this.vx*=-.85; } if (this.y<-400) { this.y=-400; this.vy*=-.5; } else if (this.y>400) { this.y=400; this.vy*=-.5; } };

Now you must also be sure to call this function. The best way to do this would be a simple function call embedded in the render function, as such:

SpaceWord.prototype.render = function() { var zActual = Object.environment.fl+this.z-Object.environment.cam.z; // has the object moved behind the camera? if (zActual>0) { // object is still visible // calculate scale var scale = Object.environment.f1/zActual; // set position using camera as an offset this._x = (this.x-Object.environment.cam.x)*scale; this._y = (this.y-Object.environment.cam.y)*scale; // set size this._xscale = scale*100; this._yscale = scale*100; } else { // object has moved behind camera // reposition further down the line this.z += Object.environment.f1*2 ; // enable button this.btnSquare.enabled = true; this.btnSquare._visible = true; } // let the word move about! this.float(); };

The position of the SpaceWord is modified by two velocity variables : vx and vy . In turn , very small random forces modify the velocity variables. The SpaceWord is kept within a reasonable range by checking to see if it has exceeded the boundaries. When the object does exceed the boundary, the word is placed back within the limits and its velocity is reversed and dampened.

Camera Autofocus

One potential problem of the free-floating words feature is that the camera is now unable to focus on a moving word. You can fix this problem by writing a small function allowing the camera to track a target. The best place to put this new function is within the loop the camera is already using to move to its destination. As you may recall, this loop is on frame 1 of the main timeline. You simply need a few additional lines of code to reassign the destination if the word has moved (these changes have also been made in textInSpace_floating.fla ):

this.onEnterFrame = function() { // does the camera have a moving target if (this.cam.targetWord!=null) { // yes - reassign the destination to the target's current position this.cam.dx = this.cam.targetWord.x; this.cam.dy = this.cam.targetWord.y; } // move the camera to its destination this.cam.x += (this.cam.dx-this.cam.x)/10; this.cam.y += (this.cam.dy-this.cam.y)/10; this.cam.z += (this.cam.dz-this.cam.z)/30; };

You also need to append some code in the selection event of the SpaceWord so that the camera knows which word it is focused on. You do this by adding a single line to the constructor function in frame 1 of the SpaceWord definition layer:

// constructor function SpaceWord() { // set up button functionality this.btnSquare.onPress = function() { // push the camera towards the word by setting destination just a bit in front Object.environment.cam.dx = this._parent.x; Object.environment.cam.dy = this._parent.y; Object.environment.cam.dz = this._parent.z+Object.environment.f1*.9 ; // disable and hide button this.enabled = false; this._visible = false; // inform the camera of its new target Object.environment.cam.targetWord = this._parent; }; // set continual function to render word this.onEnterFrame = this.render; }

The new text system is a bit more irregular as the camera may or may not always be able to keep up with the SpaceWord , but this is how you might expect things to happen in the real world.

Atmospheric Fog

One final enhancement you can make to this system involves another trick of the faux-3D trade: fog. In real-world scenarios, fog, or atmospheric perspective, can be a natural indication of distance. The further away an object is, the more the particulate matter in the atmosphere will obscure its visibility. You can simulate this effect with attractive results using the _alpha movie clip property. Introducing fog also eliminates the distracting side effect caused by repositioning words in the distance. Instead of simply popping into existence, each word gradually fades in from the bright white background. This final modification exists in a file called textInSpace_fog.fla .

To add fog, you simply compute some value for _ alpha within your SpaceWord 's render function. The most logical place to place the code is just after the setting of the size:

// set size this._xscale = scale*100; this._yscale = scale*100; // set fog this._alpha = 100 - 100 * zActual/(Object.environment.f1*1.1);

Though the fog effect does require a significant amount of additional computation, the results, we believe, are worth it:

Категории