On this page, we discuss issues related to bitmap fills and embedding image files in a fla file. We also point out some minor modifications in our applet's 3D code as compared to our 'Simple 3D Drawing in Flash CS3' tutorial.
To create bitmap fills for the projections of the tetrahedron's faces, we imported our four thumbnails to the Library. To do that, go to File --> Import --> Import to Library, and then navigate to to an image file that you want to import, say LiliesSmall.jpg. LiliesSmall appears now in the Library. To be able to access it from our script, we have to link it to ActionScript. To establish such a linkage, select LiliesSmall Library item, go to the small menu icon in the upper right corner of the Library window, and click on 'Linkage' menu item. A dialog box appears. Select 'Export for ActionScript'. As you see our base class is flash.display.BitmapData, class name is LiliesSmall. Click OK. Flash tells you it will create a class LiliesSmall, say Yes to it. Flash has created a subclass of the BitmapData class called LiliesSmall. This class holds all the pixel information about our small lilies. (See a note at the end of this page for a discussion of the Bitmap versus BitmapData classes.) Having created LiliesSmall class we can now instantiate it and manipulate it in our sript. We link all four of our thumbnails to AS.
In the script, we create instances of the new classes on lines 45-51:
var bdSunset:BitmapData=new SunsetSmall(30,23);
var bdHills:BitmapData=new HillsSmall(30,23);
var bdLilies:BitmapData=new LiliesSmall(30,23);
var bdWinter:BitmapData=new WinterSmall(30,23);
The BitmapData class constructor requires at least two parameters: width and height in pixels. Thus, we pass the size of our thumbnails, 30 by 23 pixesl, to the constructor. Since LiliesSmall etc. are custom subclasses of the BitmapData class (and thus new datatypes), we could have used:
var bdSunset:SunsetSmall=new SunsetSmall(30,23);
var bdHills:HillsSmall=new HillsSmall(30,23);
var bdLilies:LiliesSmall=new LiliesSmall(30,23);
var bdWinter:WinterSmall=new WinterSmall(30,23);
We are typing to its superclass, BitmapData, to illuminate the meaning of the BitmapData class.
For convenience, we store our BitmapData instances in an array:
var bitFills:Array=[bdSunset,bdWinter,bdLilies,bdHills];
Unlike in Simple 3D Drawing in Flash CS3 tutorial, the faces of the tetraheron will now respond to mouse events. Thus, we draw the projection of each face in a separate Sprite. Those Sprites are spFaceHolder0, spFaceHolder1, etc. and are children of spBoard. spBoard, as in the Simple 3D tutorial, is the main container for all drawings and appears on the Stage as the light gray square. Here is the corresponding code:
var spBoard:Sprite=new Sprite();
this.addChild(spBoard);
spBoard.x=150;
spBoard.y=220;
var shBack:Shape=new Shape();
spBoard.addChild(shBack);
drawBack();
var spFaceHolder0:Sprite=new Sprite();
spBoard.addChild(spFaceHolder0);
var spFaceHolder1:Sprite=new Sprite();
spBoard.addChild(spFaceHolder1);
var spFaceHolder2:Sprite=new Sprite();
spBoard.addChild(spFaceHolder2);
var spFaceHolder3:Sprite=new Sprite();
spBoard.addChild(spFaceHolder3);
We will want the faces to respond to a double-click. Interestingly, to enable an InteractiveObject to respond to a double-click, you need to do so explicitly:
spFaceHolder0.doubleClickEnabled=true;
spFaceHolder1.doubleClickEnabled=true;
spFaceHolder2.doubleClickEnabled=true;
spFaceHolder3.doubleClickEnabled=true;
In setVertices and setFaces functions, we made obvious modifications by entering the coordinates of the tetrahedron's vertices and its faces. Here is the portion of the code within renderView function that is related to bitmap fill:
function renderView(t:Number,p:Number):void {
.................
//In our case, numFaces is 4 as the tetrahedron has 4 faces.
for(i=0;i<numFaces;i++){
.................
distArray[i]=[dist,i,this["spFaceHolder"+String(i)]];
}
distArray.sort(byDist);
//'byDist' is a function defined in the portion of the script not reproduced here.
for(i=0;i<numFaces;i++){
curFaceHolder=distArray[i][2];
/*
We draw in the current curFaceHolder and place it in front of the rest.
Note that distArray has been sorted, so faces (more precisely, face holders)
appear in the array in order, from the farthest to the closest to the observer.
*/
curFaceHolder.graphics.clear();
spBoard.setChildIndex(curFaceHolder,spBoard.numChildren-1);
curFaceNum=distArray[i][1];
//In our case, curFaceLen is always 3 as each face has 3 vertices.
curFaceLen=facesArray[curFaceNum].length;
curFaceHolder.graphics.lineStyle(3,0xCC0000);
/*
Instead of filling the projection of each face with a solid color,
we use bitmap fills. beginBitmapFill method requires at least one parameter
of the type BitmapData. Recall that our BitmapData objects have been stored
in bitFills array. So bitFills[curFaceNum] is the BitmapData object
corresponding to the face number curFaceNum that is being drawn. For each face,
our BitmapData consists of pixel information extracted
from our thumbnails. The thumbnail will be reproduced,
and then repeated to fill the region being drawn. Besides the first line,
the process of drawing a bitmap fill is the same as for ordinary fills.
Note that dispArray holds the coordinates of the projections of the vertices
of the current face being drawn.
*/
curFaceHolder.graphics.beginBitmapFill(bitFills[curFaceNum]);
curFaceHolder.graphics.moveTo(dispArray[facesArray[curFaceNum][0]][0],
dispArray[facesArray[curFaceNum][0]][1]);
for(j=1;j<curFaceLen;j++){
curFaceHolder.graphics.lineTo(dispArray[facesArray[curFaceNum][j]][0],
dispArray[facesArray[curFaceNum][j]][1]);
}
curFaceHolder.graphics.lineTo(dispArray[facesArray[curFaceNum][0]][0],
dispArray[facesArray[curFaceNum][0]][1]);
curFaceHolder.graphics.endFill();
}
.................
}
A Note on beginBitmapFill(...). As you see, beginBitmapFill(...) is used just like beginFill(..). The only difference is in the arguments that the method takes. The one argument that must be provided is a BitmapData object as we provided above. Optional arguments are: a transformation matrix (an instance of flash.geom.Matrix, default null, i.e. no transformation), repeat true or false (default true), smooth true or false (default false). As you see, our small image is being repeated to fill the region that it is supposed to fill.
A Note on Bitmap and BitmapData classes. As you have seen, when we linked our thumbnails to ActionScript they became objects of BitmapData type. And good that they did as we need that type object for the beginBitmapFill method. BitmapData is a helper class to the Bitmap class. For an instance of the Bitmap class, the property bitmapData: yourBitmap.bitmapData is a BitmapData object that holds all the pixel information of yourBitmap. An instance of BitmapData cannot be manipulated directly or event added to the Display List. It has to be wrapped into a Bitmap object first.
If you wanted to manipulate programmatically our WinterSmall Bitmapdata object, stored in the variable bdWinter, you would have to do something like this:
var bmp:Bitmap=new Bitmap();
bmp.bitmapData=bdWinter;
this.addChild(bmp);
Now you can apply the many methods of the Bitmap class to bmp. For example:
bmp.scaleX=3;
bmp.x=200;
The many ways of connecting Bitmap objects with BitmapData objects and manipulating them deserves a separate tutorial. (Upcoming!)
Of course, if you drag WinterSmall onto the Stage, it does become a Bitmap object and you can manipulate it directly.
On the next page we discuss the Loader class and loading jpegs at runtime. We will also look at event listeners that provided us with desired functionality.










