Label

  • ActionScript 2
  • AD Player 2
  • Algorithm 2
  • AS3 16
  • Audio 1
  • Audio Description Player 1
  • Bitmap 1
  • BitmapData 1
  • Browser 1
  • C# Experience 4
  • Chart 1
  • Flash 10
  • Game 1
  • Geometry 1
  • JavaScript 2
  • Mathematics 6
  • Music Online 1
  • MVC 1
  • Performance 1
  • PureMVC 1
  • Slide 1
  • Talks 1
  • Tool 1
  • Tool Player 1
Toggle Side
Home   »   AS3

Ocean Paradise Game

Show off to you my world fish, ocean paradise game :D
My fish game is just one of several my prototype game built on flash two years ago. Several calculation methods as perspective, direction, gravity of the game is applied Vector2D, a library is very useful to me. Whoever created great achievements must also have started to learn, and I am also proud that I have studied and inherit the research achievements of predecessors :D :D
This project couldn't continue because it has not received adequate investment.

Author relations:
- Graphic design: Thanh Nhan, Hoai Anh
- Music: Khanh Duong Phan
- R&D: Hung Le

Reference:
- http://www.zambetti.com/projects/vector2d/
- Download Vector2D.as3

Tag: Vector2D.as, Vector2D, algorithm, mathematics
Labels: AS3 ,  Game   at:  11:00 AM     0   comments

Basic form for formula of mathematics

Building the basic form to show the mathematical formula. - The project will start from 25/3/2012

Source: https://mathbase.googlecode.com/svn
Labels: AS3 ,  Mathematics   at:  2:03 AM     0   comments

Bar Chart with AS3

I was interacting with a resource management tool project, SourceOffSite - a client version for check in and check out the project source, I often work with SVN and often observed Repository-Statistics - graph chart of statistics for the code have been sent to the server, this statistic is quite interesting and a part to help you a little feel the project.
Let's see Repository-Statistics of a project: http://www.redmine.org/projects/redmine/repository/statistics
Returning to the problem that I am referring, rummage everything in SourceOffSite I found the task to extract CSV report, with this report I can use excel to view but for the statistical uncertainty. After a short time, I analyzed the CSV data sources, and what I need then display this data in the form of Bar Chart, I tried to find some of Bar Chart shows content but have unsuccessful. Everything that commercial, I decided to save time and write something useful....namely Bar Chart for free!.





Extremely easy to use and is very quick!

Download

1. non-crossdomain
2. Crossdomain
3. JavaScript SWFObject Embed for Flash

Reference:

1. http://code.google.com/p/swfobject/downloads/list
2. http://code.google.com/apis/chart/interactive/docs/gallery/barchart.html
3. http://code.google.com/apis/chart/image/docs/gallery/bar_charts.html
4. http://code.google.com/apis/chart/interactive/docs/gallery.html
5. http://code.google.com/apis/chart/interactive/docs/gallery/imagebarchart.html
Labels: AS3 ,  Chart   at:  4:26 PM     0   comments

Read all the node of MovieClip

You can write a small tool to read all the MovieClip, take very easy!
My simple code:
/*
* read all and push to list
*/
private function readObject(mc:Object):void {
var mcs:* = null;
var mci:* = null;
for (var i:int = 0; i < mc.numChildren; i++ ) {
mcs = mc.getChildAt(i);
list.push(mcs);
if (mcs is MovieClip) {
if (mcs.numChildren > 0) {
readObject(mcs);
}
}
}
}
/**
* Example:
* input: object[child]
* output: string[root.parent.parent.child]
* @param object
* @return string
*/
private function readParent(object:*):String {
var str:String = "";
if (object != null) {
var temp:Array = new Array();
while (object.parent != null) {
temp.push(object.name);
object = object.parent;
}
temp = temp.reverse();
}
return String(temp).split(",").join(".");
}

Demo



Labels: AS3 ,  Flash   at:  4:25 PM     0   comments

Audio Description Player

ADPlayer v1.0.0.0:

  • Player track and throw out position.
  • Click to content send position that's the track will be jump.

ADPlayer Embed Example

Include the ADPlayer JavaScript library in the head of your HTML page
<html>
<head>
<title>ADPlayer dynamic embed</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body{
font-family:Tahoma;
font-size:12px;
color:#484848;
}
a.transcriptLink {
outline: none;
text-decoration: none;
color:#484848;
}
a.transcriptLink:hover, a.transcriptLink:active {
outline: none;
text-decoration: none;
background: #d2d1d0;
}
</style>
<script type="text/javascript" src="adplayer.js"></script>
</head>
<body>
<div id="yourembedflash"></div>
<div id="sourcedata" style="overflow: auto;" class="transcript">
<p>
<a href="0" class="transcriptLink">I am a writer.</a>
<a href="2000" class = "transcriptLink">Writing books is my profession... </a>
</p>
</div>
<script type="text/javascript">
// [0] create here
</script>
</body>
</html>

Embed your SWF with JavaScript
Example:
try{
var ebonc = new ADPlayer();
ebonc.id = 'flashid';
ebonc.swf = 'flash.swf';
ebonc.divid = 'yourembedflash';
ebonc.handler = 'ebonc';
ebonc.base = 'sourcedata';
ebonc.variable.src = 'trackfile.mp3';
ebonc.variable.title = "Artists - Titles";
ebonc.variable.overhand = true;
ebonc.variable.reading = true;
ebonc.variable.rightclick=true;
ebonc.install(true);
}catch(ex){
}

ADPlayer JavaScript API

Parameters and Variables
var ebonc= new ADPlayer()     // ebonc is the name I created as form     
ebonc.id    
ebonc.swf
ebonc.divid
ebonc.handler
ebonc.base
ebonc.variable.id
ebonc.variable.src
ebonc.variable.title
ebonc.variable.crossdomain
ebonc.variable.insecure
ebonc.variable.policy
ebonc.variable.playerid
ebonc.variable.handler
ebonc.variable.rightclick
ebonc.variable.autostart
ebonc.variable.animation
ebonc.variable.minisize
ebonc.variable.overhand
ebonc.variable.reading
ebonc.variable.version
ebonc.variable.volume

Detail
  • ebonc.id
    Define the id for flash embed, this is required!
  • ebonc.swf
    Link flash file
    Example: http://yoursite.com/adplayer.swf
    or
    /abc/adplayer.swf
  • ebonc.divid
    Where you want to embed flash file.
    Example: ebonc.divid="divembedid";
    <div id="divembedid">
      <embed id="flashid" />
    </div>
  • ebonc.handler
    This is the variable of ADPlayer or Player that you have declared
    Example:
    var ebonc= new ADPlayer(); //or new Player();
          ebonc.handler = "ebonc";

    var newaudio= new ADPlayer(); //or new Player();
          newaudio.handler = "newaudio";
    ...
  • ebonc.base ID, Area or location where the text contains that is the handler will be get data for flash.
    the data is essentially the links ,within it have ID , each ID is a sound position.
    Example:
    <div id="datasource">
     <a id="0">I</a><a id="100">love</a><a id="200">my friends</a>
    </div>
    so
    ebonc.base = "datasource";
  • ebonc.variable.id
    This you can ignore , ignore that is not declared this variable
  • ebonc.variable.src  Link audio file
    Example: http://yourhot.com/hello.mp3
    or
    /abc/hello.mp3
  • ebonc.variable.title
    Title's audio. May be include titles and articles
    Example:

    Title here: Elizabeth Gilber...

  • ebonc.variable.crossdomain
    Default (*)
    On flash as flash.system.security.allowDomain('*')
    You can custom it as the case may be, about development, I'm sure you know.
  • ebonc.variable.insecure
    Default (*)
    On flash as flash.system.security.allowInsecureDomain('*')
  • ebonc.variable.policy
    Default empty ''
    On flash as flash.system.Security.loadPolicyFile('');
  • ebonc.variable.playerid
    Default 192.168.1.1 That is id separate the configure of the sound.
  • ebonc.variable.handler
    You don't need to define, default: ebonc.variable.handler = ebonc.handler = "ebonc";
  • ebonc.variable.rightclick
    true or false, When you use the right mouse and click on the process bar, immediate position of the track will be placed in the position where the mouse click, Note: if you don't want to use the right mouse the does not need to declare, default is false.
  • ebonc.variable.autostart
    true or false, auto play if true, default is false.
  • ebonc.variable.animation
    true or false, default is false.
    open state
    close state
  • ebonc.variable.minisize
    true or false, default is false.
    close state open state
    In the case the "minisize" is the true state, then the "animation" is not meaningful.
  • ebonc.variable.overhand
    true or false, default is false.
    A feature allows the sound to the position of the corresponding content and to the contrary.
    When you click on the content , the track will jump to the position of the content on the process bar, When you click on the process bar, the content is highlighted will jump to the position and continue play.
  • ebonc.variable.reading
    true or false, default is false.
    The process of the sound is move, the content is highlighted, and if you set false, it'll not highlight content.
  • ebonc.variable.version
    true or false, when you right click on the Flash you'll see develop version, in case you don't like , you can hide it.
    if true is show else hide.
  • ebonc.variable.volume
    Variable is the value of Number, Float [0-1], default: 0.6

API function
var ebonc= new ADPlayer() // Or new Player()
// parameters...
// variables ...
ebonc.install() //
ebonc.process() //
ebonc.change() //


Detail
Coming soon!
Labels: AS3 ,  Audio ,  Flash ,  JavaScript   at:  2:51 AM     0   comments

MovieMix and MoviePix width demo

MovieMix
MovieMix is a Class transcribed by another Class of the author Sascha on blog.hexagonstar.com
Its mission is to turn a regular bitmap into animated bitmap. I was surprised and delighted to extend it, From there, I've developed based on the Hexagonstar's AnimatedBitmap in the first version.
In the AnimatedBitmap, data input into is a BitmapData(ImageSequence a horizontal line)

Corresponds to rendering:
//thisbuffer as ImageSequence a horizontal line
bitmapData.copyPixels(thisbuffer, new Rectangle((framenr - 1) * onwidth, 0, onwidth, onheight), new Point());
In the MovieMix, data input into is a list BitmapData that stored in DataMix.
Corresponds to rendering:
var db:BitmapData = listbitmap[framenr - 1]; // listbitmap as Array
bitmapData.copyPixels(db,db.rect,new Point(0,0));

Oh yes, reading from Array list to get BitmapData, maybe you'll appreciate it not better by shifting the position, because the process of reading data in an array will take the CPU processing time,
you're right but be assured, processing time there is will not come up too costly in the case of small array.

Anyway, here is a great performance tester written by author Nicolas.
http://bimeanalytics.com/projects/performance_tester/performanceTester.html

And here is my demo:




MovieMix with data is Array of the BimapData



MoviePix
To expand my method to render data I write a different class, instead of read from Array as MovieMix, I'll write to read from BitmapData, Bitmap is an ImageSequence(multi line) and I named it as MoviePix.
For the process of writing a BitmapData and reading BitmapData is the same correlative, I created a "Big BitmapData" in DataMix (read more wiki DataMix version 1.0.0.4 here) and readed same method:
var thisframe:Number = framenr - 1;
var sizeW:Number = this.width;
var sizeH:Number = this.height;
var bufW:Number = thisbuffer.width;
var bufH:Number = thisbuffer.height;
var column:Number = bufW / sizeW;
var x:Number = ( thisframe % column ) * sizeW;
var y:Number = Math.floor( thisframe / column ) * sizeH;
//thisbuffer as Image sequence multi lines
bitmapData.copyPixels(thisbuffer, new Rectangle(x, y, sizeW, sizeH), new Point());
The above method rended by shifting the position, you can fully trust that it runs lighter then reading from the array.

For demo to easily imagine.





MoviePix with data is a big of the BimapData




Flowchart:
DataMix offers two types of data, an Array BitmapData and a Big BitmapData

Reference:

http://blog.odcup.com/2011/12/movieclip-to-animated-bitmap.html
http://blog.hexagonstar.com/animatedbitmapclass/
http://bimeanalytics.com/projects/performance_tester/performanceTester.html
http://jacksondunstan.com/articles/479

Labels: AS3 ,  Flash   at:  10:33 PM     0   comments

DataMix and useful apps - Part 1

A colleague of mine was struggling with what to trial software that converts SWF files into a different picture. The purpose of this transformation is to find optimized solutions from the Vector Graphic to Bitmap. I asked him why did not write a small software to serve this purpose. Oh, I've forgotten he's designer.

I go back to a data processing class which I wrote several weeks ago.
DataMix is a data processing class from MovieClip forms converted into BitmapData
and from the BitmapData you can easily use for different purposes such as conversion into the image, block images or use them for MovieMix, MoviePix.

This is a general model of transition.

The blocks of images

Demo:
//mc as MovieClip
var dx:DataMix = new DataMix(mc);
var zip:ASZip = new ASZip(CompressionMethod.GZIP);

for (var i:int = 0; i < dx.length; i++) {
var bytes:ByteArray = PNGEncoder.encode(dx.data[i]);
//zip.addDirectory ("pics/");
//zip.addFile (bytes, "pics/F1_"+i+".png");
zip.addFile (bytes, "F1_"+i+".png");
}
var file:ByteArray = zip.saveZIP ( Method.LOCAL );

var fr:FileReference = new FileReference();
fr.save(file, "pics.zip");


you've got a useful tool!

Reference:
DataMix Wiki
As3ZIP Lib 2.0
Codeazur with fzip



Labels: AS3 ,  Flash   at:  3:15 PM     0   comments

MovieClip to Animated Bitmap

I have a MovieClip with distorted images of multiple frames, frame images in a continuous motion would alter the surface area of the frame, adding that the movement of images on different frames so not on a coordinate axis identified with Center Point(0,0).
The problem I have to do is convert a Movie Clip to "Animated Bitmap", this seems a bit funny and why you must do so while the MovieClip fully cover the essentials!.
In a small application, if using MovieClip in Vector format, cloned into multiple small objects will become very heavy and consume a lot of CPU.

DESCRIPTION MATHMATICS
We often have terrible head and the horrible project if not that is what troubles, and from a multitude of troubles with a very interesting problem, module creates a moving object in a space " undefined" before,on each frame to show they are not of concern to mold Center Point(0,0) , as long as the picture shows the contents still ensure quality from frame to frame logical end.


Figure 1: Picture shows 3D perspective of all the general frames [1..15]


Figure 2: Face image - overview of moving images


Figure 3: Performance of range to range across the frames

This is what the designer is usually created, a product which, if they are not associated with other products or be required in certain cases. Back to module, module should be mounted above the joint with a larger project, This project will show it on stage, cloned it into several sub-objects, and move it in space, the success of this module will be very meaningful for us to improve the processing speed of CPU. In a specific example we will make a horse race in the form of MovieClip through "Animated Bitmap" as the figure below:


The horse racing with images shown will be Alnimal Bitmap

PROBLEM SOLVING

Step 1: Determine the total area of MovieClip including coordinates deviation [x, y, with, hight] compared with Center Point(0,0) as the figure below:


Code:
/**
* Determine the total area and the initial coordinates of the object.
* @param mc
* @return Rectangle
*/
private function getRecBase(mc:MovieClip):Rectangle {
var totalframe:int = mc.totalFrames;
var maxx:Number = NaN;
var maxy:Number = NaN;
var minx:Number = NaN;
var miny:Number = NaN;
var maxw:Number = NaN;
var maxh:Number = NaN;
var temp:Number = NaN;
var temw:Number = NaN;

for (var i:int = 1; i <= totalframe; i++) {
mc.gotoAndStop(i);
var b:Rectangle = mc.getBounds(mc);

minx = ((temp = b.x) < minx)?temp:(isNaN(minx))?temp:minx;
miny = ((temp = b.y) < miny)?temp:(isNaN(miny))?temp:miny;
maxw = ((temp = b.width) > maxw)?temp:(isNaN(maxw))?temp:maxw;
maxh = ((temp = b.height) > maxh)?temp:(isNaN(maxh))?temp:maxh;

maxx = ((temp = b.x + b.width) > maxx)?temp:(isNaN(maxx))?temp:maxx;
maxy = ((temp = b.y + b.height) > maxy)?temp:(isNaN(maxy))?temp:maxy;
}

var maxwi:Number = maxx - minx;
var maxhi:Number = maxy - miny;
//Note!
var pon:Sprite = new Sprite();
pon.graphics.beginFill(0x999999, 0);
pon.graphics.drawRect(minx, miny, maxwi, maxhi);
pon.graphics.endFill();
mc.addChild(pon);

var wi:Number = dePercent(mc.scaleX * 100, 0, maxwi);
var hi:Number = dePercent(mc.scaleX * 100, 0, maxhi);
return new Rectangle(minx, miny, wi, hi);
}

Step 2: Convert each frame into an image based on "Rectangle Base" in step 1, then save them into an array.

Figure 4: The array coverage marketing images in 3D

Code:
/**
* Retrieving images based on the basic rectangle
* @param mc
* @param rec
* @return
*/
private function getListBase(mc:MovieClip, rec:Rectangle):Array {
var totalframe:int = mc.totalFrames;
var list:Array = new Array();
for (var i:int = 1; i <= totalframe; i++) {
mc.gotoAndStop(i);
list.push(getBaseBitmapData(mc,rec,true ));
}
return list;
}
Step 3: After getting the BitmapDataBase in step 2 we need to remove the excess acreage unnecessary based on RectangleBase, this means that we will find an area based on what has been eliminated. Why do we have? Because the MovieClip object may contain objects "transparent " excess, This excess increases the area of " RectangleBase " when creating an image, content of the image will not show all of those parts, so we need to remove them. Also in this step we make moving pictures of coordinates Center Point(0,0).


Code:
/**
* Find a new Rectangle not including the superfluous
* @param list
* @param rec
* @return
*/
private function getRecActual(list:Array,rec:Rectangle):Rectangle {
var minx:Number = NaN;
var miny:Number = NaN;
var temp:Number = NaN;
var data:BitmapData;
var vbt:Rectangle;
for (var i:int = 0; i < list.length; i++) {
data = list[i] as BitmapData;
vbt = getViboty(data, rec);
minx = ((temp = vbt.x) < minx)?temp:(isNaN(minx))?temp:minx;
miny = ((temp = vbt.y) < miny)?temp:(isNaN(miny))?temp:miny;
}
return new Rectangle(minx, miny, rec.width - minx, rec.height - miny);
}
/**
* Get visible bounds of transparent
* [1] Frees memory that is used to store the BitmapData object.
* @param mc
* @param rec
* @return
*/
private function getViboty(mc:BitmapData,rec:Rectangle): Rectangle {
var data:BitmapData = new BitmapData(rec.width, rec.height, true, 0x00000000);
data.draw(mc);
var trec:Rectangle = data.getColorBoundsRect(0xFFFFFFFF, 0x000000, false);
data.dispose(); //[1]
return trec;
}

Step 4: After getting a "RectangleActual" in step 3, we proceed to create images based on "RectangleActual" and the base image was obtained from step 2, then save them into an array, this array is considered as the basis for "Animated Bitmap".

Code:
/**
* [1] Frees memory that is used to store the BitmapData object.
* @param list
* @param newrec
* @return
*/
private function getListActual(list:Array, newrec:Rectangle):Array {
var data:BitmapData;
var newlist:Array = new Array();
for (var i:int = 0; i < list.length; i++) {
data = list[i] as BitmapData;
newlist.push(getActutalBitmapData(data, newrec));
}
clearListBase(list); //[1]
return newlist;
}

Finally, create a class from the above general and named DataMix. This class three basic methods are: width, height, and restore the image as Array.

var dm:DataMix = new DataMix(mc);
dm.width;
dm.hight;
dm.data; // as Array

And from here we can completely assured when working with a design deviation without worrying that our results can be misleading.
Come back DataMix, make DataMix motion, we put it into a MovieMix that I wrote long before DataMix birth.
Do you believe it works? Try that!
var dm:DataMix = new DataMix(mc);
var mx:MovieMix = new MovieMix(dm.data, dm.width, dm.height,stage.frameRate);
addChild(mx);

Demo:






Source:
DataMix.as
MovieMix.as
MoviePix.as
EnterFrame.as

Wiki:
Wiki DataMix

Note:
Remove the package name when you want to use it.

The last reference:
Animated Bitmap Class by Hexagonstar
Understanding the Transformation Matrix
Lab.polygonal.de
Preorder and postorder traversal
Labels: AS3 ,  Flash ,  Geometry   at:  11:15 PM     2   comments

Bubbles air AS3

A real time, randomly generated, ActionScript animation of water bubbles, that starts from the bottom and reach the top. The bubbles are vector graphics, so you can resize them.




Movement mode = -1 Movement mode = 0 Movement mode = 1





You can easily change the parameters that rule the bubbles generation, to customize the animation for your needs. You can change:

  • maximum number of bubbles
  • average speed
  • alpha and size interval
  • oscillation speed and amount
  • fade-in and fade-out effect
  • blur effect

It’s also easy to change the bubble graphic (just edit the movieclip) or the background.
You can also put it in an html page using a transparent background, for a really nice effect.

Download source:
  • Bubbles.as AS3 Class
    • http://hutra.googlecode.com/files/bubbles.zip
  • BubblePlus.as AS3 Class, fla implement BubblePlus
    • Bubbles.fla Flash CS4 IDE
    • Bubbles.swf Flash Player 10, AS3
    • BubblePlus.as AS3
    • http://hutra.googlecode.com/files/bubbles_fla_implement.zip


Reference:
http://activeden.net/item/water-bubbles-v2-real-time-as3-animation/41599
Labels: AS3 ,  Flash   at:  12:56 AM     4   comments

DataMix

Version 1.0.0.1
DataMix is a fundamental component allows to convert from MovieClip to Animal Bitmap, DataMix store the BitmapData's after analysis & processing from MovieClip with methods basic: width, hight, total BitmapData.

The constructor:

/**
* In special cases, we only get the size, no need to get data
* @param mc as MovieClip with multiple frames
*/
public function DataMix(mc:MovieClip)
The basic property public:

// mc as MovieClip with multiple frames
var dm:DataMix = new DataMix(mc);
dm.width; // as Number
dm.hight; // as Number
dm.data; // as Array [BitmapData,BitmapData,BitmapData,...]


The basic methods private:

//[1] function support
function movePosition(a:Number, b:Number):Number;
function dePercent(p:Number, s:Number = 0, e:Number = 100):Number;
//[2]
function getRecBase(mc:MovieClip):Rectangle;
function getListBase(mc:MovieClip, rec:Rectangle):Array;
function getBaseBitmapData(mc:MovieClip, rec:Rectangle, smoothing:Boolean ): BitmapData;
//[3]
function getRecActual(list:Array,rec:Rectangle):Rectangle;
function getViboty(mc:BitmapData,rec:Rectangle): Rectangle
function getListActual(list:Array, newrec:Rectangle):Array;
function getActutalBitmapData(bitmapdata:BitmapData, rec:Rectangle): BitmapData;

[2]
Figure 1: Get list BitmapData base
[3]

Figure 2: Get lis BitmapData from list BitmapData base

The last reference:
18 Useful mathematical formulas in ActionScript 3
MovieClip to Animal Bitmap

Source:
DataMix.as version 1.0.0.1



Version 1.0.0.2
In this version, DataMix only get true size of the MovieClip, it's not store the BitmapData
Changes in the Constructor

/**
* In special cases, we only get the size, no need to get data
* @param mc as MovieClip
* @param isdata if true get all including data else false only get size
*/
public function DataMix(mc:MovieClip,isdata:Boolean=true)

For example:
// mc as MovieClip with multiple frames
var dm:DataMix = new DataMix(mc);
dm.width; // 100
dm.hight; // 100
dm.data; // null

Source:
DataMix.as version 1.0.0.2



Version 1.0.0.3

Completely remove the excess in list BitmapData, you can see the difference in version 1 2 and 3

/**
* @param mc Make sure you seted the movie correctly!
*/
private function setup(mc:MovieClip,isdata:Boolean):void {
var recBase:Rectangle = getRecBase(mc);
var listBase:Array = getListBase(mc, recBase);
var recActual:Rectangle = getRecActual(listBase, recBase);

var listFace:Array = getListActual(listBase, recActual);
var recTrim:Rectangle = getTrimBitmapData(listFace);

w = recTrim.width;
h = recTrim.height;

if (isdata) {
clearListBase(listBase); // necessary!
d = getListActual(listFace, recTrim);
}else {
clearListBase(listBase); // necessary!
clearListBase(listFace); // necessary!
d = null;
}
}
/**
* The function trim a bit transparent in the Bitmapdata
* @param a list BitmapData actual, but non-trim
* @return rectangle
*/
private function getTrimBitmapData(a:Array):Rectangle {
var maxx:Number = NaN;
var maxy:Number = NaN;
var minx:Number = NaN;
var miny:Number = NaN;
var maxw:Number = NaN;
var maxh:Number = NaN;
var temp:Number = NaN;
for (var i:int = 0 ; i < a.length; i++){
var b:Rectangle = a[i].getColorBoundsRect(0xFFFFFFFF, 0x000000, false);

minx = ((temp = b.x) < minx)?temp:(isNaN(minx))?temp:minx;
miny = ((temp = b.y) < miny)?temp:(isNaN(miny))?temp:miny;
maxw = ((temp = b.width) > maxw)?temp:(isNaN(maxw))?temp:maxw;
maxh = ((temp = b.height) > maxh)?temp:(isNaN(maxh))?temp:maxh;

maxx = ((temp = b.x + b.width) > maxx)?temp:(isNaN(maxx))?temp:maxx;
maxy = ((temp = b.y + b.height) > maxy)?temp:(isNaN(maxy))?temp:maxy;

}
var maxwi:Number = maxx - minx;
var maxhi:Number = maxy - miny;
return new Rectangle(minx, miny, maxwi, maxhi);
}



Figure 3: Get trim BitmapData, completely remove the transparent

For example:

Old version (left ) and new version (right)

Source:
DataMix.as version 1.0.0.3


Version 1.0.0.4

Creating source BitmapData that is used for a large image with contains render multiple images children.

// mc as MovieClip with multiple frames
var dm:DataMix = new DataMix(mc);
//Return value bitmapData that is parse from data.
dm.bitmap; // as big BitmapData;

For example:
var dx:DataMix = new DataMix(mc); // mc as MovieClip with multiple frames
var bitmap:Bitmap = new Bitmap(dx.bitmap);
addChild(bitmap);
Bitmap is taken from DataMix

Source:
DataMix.as version 1.0.0.4









Labels: ActionScript ,  AS3 ,  Bitmap ,  BitmapData ,  Flash   at:  4:18 PM     0   comments

How old are you?

Not long ago, a friend asked my age, I assured her that I had reached the age Y but she insisted that I just reached the age of X, said that of her I have not reached the age of Y.

How can demonstrated their age to another friend, this is simple, if you use MS Excel you can calculate the right amount of time that you went through, you can also find a web site that calculates age by clicking on the sample form, but I find a way to personal the ActionScript is adapted from JavaScript.

Usage:
var date:DateUtilities = new DateUtilities();
var currentTime:Number = Date.UTC(2011, 11, 05, 12, 12, 12, 12);
var birthDate:Number = Date.UTC(1985, 01, 01, 06, 30, 12, 12);
var old:String = date.qryHowOld(currentTime, birthDate);
//result: 26 years 9 months 2 weeks 3 days 5 hours

I try to create examples to avoid falling into oblivion, at least I am using this code, welcome everybody :)

Demo:








Source:

DateUtilities.as
Dater.as

Labels: AS3 ,  Flash   at:  7:19 AM     0   comments

Useful mathematical formulas in ActionScript 3

We have listed 12 very simple,basic but useful function source in Flex in the previous article. The mathematical calculation will be used regularly in our Flash applications, we can easily find the open source libraries like 30+ useful as3 open source projects, but it’s superfluous when we only need calculate the distance between two points, or only want to get the circle area. Here is the list of 18 useful AS3 arithmetic & formulas. Have any proudly and recommendable? Leave your comments to share please.

1. Distance Between Two Points




dx = x2 – x1;
dy = y2 – y1;
dist = Math.sqrt(dx*dx + dy*dy);

2. Inching Formulas
sprite.x += (targetX – sprite.x) * easing;//easing: inching coefficient
sprite.y += (targetY – sprite.y) * easing;

3. Elastic Formulas
vx += (targetX – sprite.x) * spring; //spring: elastic coefficient
vy += (targetY – sprite.y) * spring;
sprite.x += (vx *= friction); //friction: friction force
sprite.y += (vy *= friction);
4. Flexible Partial Shifts Formulas
var dx:Number = sprite.x – fixedX;
var dy:Number = sprite.y – fixedY;
var angle:Number = Math.atan2(dy, dx);
var targetX:Number = fixedX + Math.cos(angle) * springLength;
var targetY:Number = fixedX + Math.sin(angle) * springLength;

5. Rotation With Mouse Formulas
dx = mouseX – sprite.x;
dy = mouseY – sprite.y;
sprite.rotation = Math.atan2(dy, dx) * 180 / Math.PI;

6. Waveform Formulas
public function onEnterFrame1(event:Event):void {
ball.y=centerScale+Math.sin(angle)*range;
angle+=speed;
}

7. Heartthrob Formulas
public function onEnterFrame1(event:Event):void {
ball.scaleX=centerScale+Math.sin(angle)*range;
ball.scaleY=centerScale+Math.sin(angle)*range;
angle+=speed;
}

8. Circle Rotation Formulas
public function onEnterFrame(event:Event):void {
ball.x=centerX+Math.cos(angle)*radius;
ball.y=centerY+Math.sin(angle)*radius;
angle+=speed;
}

9. Get Circle Area
public function getArea():Number
{
// The formula is Pi times the radius squared.
return Math.PI * Math.pow((width / 2), 2);
}

10. Get Circumference Ratio
public function getCircumference():Number
{
// The formula is Pi times the diameter.
return Math.PI * width;
}


11. Elliptic Rotation Formulas
public function onEnterFrame(event:Event):void {
ball.x=centerX+Math.cos(angle)*radiusX;
ball.y=centerY+Math.sin(angle)*radiusY;
angle+=speed;
}

12. Color operations
var t:uint=0×77ff8877
var s:uint=0xff000000
var h:uint=t&s
var m:uint=h>>>24
trace(m);

13. Hex to Decimal
trace(hexValue);

14. Decimal to Hex
decimalValue.toString(16);

15. Pick Up Color
red = color24 >> 16;
green = color24 >> 8 & 0xFF;
blue = color24 & 0xFF;
alpha = color32 >> 24;
red = color32 >> 16 & 0xFF;
green = color32 >> 8 & 0xFF;
blue = color232 & 0xFF;


16. Color Bit Arithmetic
color24 = red << 16 | green << 8 | blue;
color32 = alpha << 24 | red << 16 | green << 8 | blue;


17. Percent of a Number
/**
* Comparing the present with a series of numbers, provided the per cent over the range of those
* @param start
* @param end
* @param current
* @return percent of the number 0 - 100 if the start
*/
public static function coPercent(c:Number, s:Number = 0, e:Number = 100):Number {
return (((e - s) - (e - c))/(e - s)) * 100;
}
//50 -> 400 ~ 100%
//50 -> 200 ~ ? %
// cal: 42.8%
//percent = NumberUtilities.coPercent(200, 50, 400);
//trace(percent); // 42.857142857142854





18. Number of a percent
/**
* Percentage change from the current number
* @param percent
* @param start
* @param end
* @return
*/
public static function dePercent(p:Number, s:Number = 0, e:Number = 100):Number {
return (e - ((e - s) - ((p/100) * (e - s))));
}
//100% ~ 50 - 400
//42.8%~ 50 - ?
// cal: 200
//number = NumberUtilities.dePercent(42.8, 50, 400);
//trace(number); // ~200



For demo 17 - 18:



19. Number of factorial
/**
* The term n! (pronounced n factorial) means multiply together all the whole numbers from 1 to n
* @param n, remember 0! = 1
* @return n!
*/
public function factorial(n:Number):Number{
var k:Number=1;
for (var i:int = 1; i <= n; i++) k = k * i;
return k;
}
//5! = 1 x 2 x 3 x 4 x 5 = 120
20. Number of factorial
/**
* The number of ways of selecting r objects from a total of n is written as
* @param n
* @param r
* @return
*/
public function combinatorics(n:Number, r:Number):Number {
return factorial(n) / (factorial(r) * factorial(n - r));
}
//5C0 = 1
//5C1 = 5
//5C2 = 10
//5C3 = 10
//5C4 = 5
//5C5 = 1

21. Pascal's Triangle
/**
* Pascal's Triangle
* @param n
* @param r
* @return
*/
public function pascal(n:Number, r:Number):Number{
if (n > 1 && r > 0 && r < n) {
var a:Number = pascal(n - 1, r - 1);
var b:Number = pascal(n - 1, r);
var c:Number = a + b;
return c;
}
return 1;
}
//(1 + x)3 = 3C0 + 3C1x + 3C2x2 + 3C3x3

0 1 2 3 4 5 6
0 1 1 1 1 1 1 1
1 1 2 3 4 5 6
2 1 3 6 10 15
3 1 4 10 20
4 1 5 15
5 1 6
6 1
Labels: AS3 ,  Mathematics   at:  6:32 AM     0   comments

Understanding the Transformation Matrix

Matrices and the Transform Matrix


Before getting into how transformation matrices (matrices is plural of matrix) work, it is important to understand what a matrix is. A matrix is a rectangular array (or table) of numbers consisting of any number of rows and columns. A matrix consisting of m rows and n columns is known as an m x n matrix. This represents the matrix's dimensions. You'll commonly seen matrices with numbers in rows and columns surrounded by two large bracket symbols.


Matrices are used for many different purposes, often to store data or solve problems using certain matrix calculations. Flash uses matrices to define affine transformations.
Affine transformations are transformations that preserve collinearity and relative distancing in a transformed coordinate space. This means points on a line will remain in a line after an affine transformation is applied to the coordinate space in which that line exists. It also means parallel lines remain parallel and that relative spacing or distancing, though it may scale, will always maintain at a consistent ratio. Affine transformations allow for repositioning, scaling, skewing and rotation. Things they cannot do include tapering or distorting with perspective. If you're ever worked with transforming symbols in Flash, you probably recognize these qualities.

The transformation matrices in Flash that define these affine transformations use a 3 x 3 matrix consisting of 3 rows and 3 columns. The positions of values within this matrix are labeled a, b, c, d, tx, ty, u, v, and w. In matrices, these are known as elements.


Elements a, b, c, d, tx, and ty are those most important to the transformation matrix. The additional positions, u, v, and w are, at this point, not important but still require to be present in the matrix. Each a, b, c, d, tx, and ty correspond to a specific type of transformation within Flash.
a - x scale
b - y skew
c - x skew
d - y scale
tx - x translation (position)
ty - y translation (position)
The u, v, and w positions are static values that remain at 0, 0, and 1 respectively.


Note:

In the Matrix class in Flash, u,v, and w are not accessible as properties as a, b, c, d, tx, and ty are.
The effective elements, or properties as they will be referred to from this point forward, a, b, c, d, tx, and ty are used in formulas for x and y when determining the position of a new x and y value resulting from the transformation applied by a matrix. These formulas are

x' = x*a + y*c + tx

y' = x*b + y*d + ty

where x and y represents the original x and y locations and x' and y' (read as x-prime and y-prime) represents the transformed locations. For any point anywhere in an image or movie clip affected by a transformation matrix, these calculations are made to determine the resulting end location for that point.

Note:

You may also see a transformation matrix represented as

or something similar (notice the u, v, and w properties at the bottom as opposed to the right). This is basically the same matrix, just with a different orientation of elements. Transformations do not change with this difference in orientation, though a few operations are handled differently when using it. The end result still remains the same.
Flash help, at the time of this writing, incorrectly represents a transformation matrix in this manner with the c and b values switched.

Identity Matrix

When a matrix causes no transformations, you have what is known as a unit or identity matrix.


Any square matrix (a matrix is square if its number of rows equals its number of columns) is an identity matrix if all values are 0 except those diagonal from the top left to the bottom right which instead have the value of 1 - the locations where the row position equals the column position. Consider what happens when an identity matrix is used with the formulas for finding a transformed x and y.
x' = x*1 + y*0 + 0

y' = x*0 + y*1 + 0

which reduces to
x' = x


y' = y

Notice that there is no change resulting from the application of the matrix; x' equals x and y' equals y. You can think of an identity matrix for matrices as being the number 1 for scalars, or regular numbers. When you multiply 1 by any number, you get the number. The same applies with the identity matrix for transformations. All new matrices in Flash, unless otherwise specified, start out as identity matrices - matrices with no transformations. This includes matrices affecting movie clips. If a movie clip has not been altered or transformed in any way, its transformation matrix is the identity matrix.

Applying Transformations

Consider what happens if the a property of an identity matrix changes. For example, what would happen if the a property in a Flash transformation matrix, starting out as an identity matrix, is changed from 1 to 2. Remember, the a property references scaling along x.

x' = 2*x + 0*y + 0

y' = 0*x + 1*y + 0

x' = 2x

y' = y

You now have a situation where all new values of x equal 2 times the old values; x' = 2x. A movie clip with the above transformation matrix would have a width double its original.


What if, instead, b was altered and given a value of 1?

x' = 1*x + 1*y + 0

y' = 0*x + 1*y + 0

x' = x + y

y' = y

Now, you have an x' value that relates not just to x but to the change in y as well. This means that as y increases, so do the resulting values of x. This causes a skew in x, the aspect of the transformation controlled by the c property.


If you wanted to shift this movie clip in any direction, you could easily change tx or ty in the matrix to do so

x' = 1*x + 1*y + 5

y' = 0*x + 1*y + 10

x' = x + y + 5

y' = y + 10

The resulting transformation is still a skew, but now the positions of x and y are just shifted by 5 and 10 respectively.

You may have noticed that there is no property in a matrix for rotation. Rotation is actually a result of a combination of scaling and skewing. Together, scaling and skewing can distort coordinates to provide what you understand as being rotation.
In simplest terms, any rotation transformation without any other types of transformations applied can be represented with the following matrix

where the angle variable represents the amount of rotation applied in the transformation.
In terms of transformation matrices, the application of rotation is often the hardest concept to grasp. Not only is there not a property for rotation as there are for aspects like scaling and skewing, but it relies on 4 other properties (scaling and skewing) to work. That within itself can be hard enough to understand but it only gets worse when you want to consider changing those other properties on top of rotation or even based on that rotation. If you're familiar enough with trigonometry and rotating vectors in 2D space, though, you may see a familiar use of sine and cosine. The same concepts apply.
Consider a simple example of a transformation matrix rotating 30 degrees.

x' = cosine(30)*x - sine(30)*y + 0

y' = sine(30)*x + cosine(30)*y + 0


x' = .87*x - .5*y

y' = .5*x + .87*y

Given the point (4, 0), a rotation of 30 degrees should provide values at about (3.5, 2) for x and y.

Plugging x=4, y=0 into the formula gives

x' = .87*4 - .5*0

y' = .5*4 + .87*0

x' = 3.46

y' = 2

Play around with a movie clip's transform matrix and watch how the transformation is applied

The ActionScript Matrix Class

A matrix in ActionScript is stored in an instance of the Flash Matrix Class. This class is located in the flash.geom package. If you create your own Matrix instance, you would need to use it's full path
var my_matrix = new flash.geom.Matrix();
or first import the class so that you may reference it using strictly "new Matrix"
import flash.geom.Matrix;

var my_matrix = new Matrix();
The Matrix constructor allows you to specify the a, b, c, d, tx, and ty properties when the instance is created.

import flash.geom.Matrix;

var my_matrix = new Matrix( a, b, c, d, tx, ty );
If no arguments are specified, you get an identity matrix.
The properties of the Matrix class are basically just a collection of your main a, b, c, d, tx, and ty properties - those you need to be concerned about when dealing with transformations. Additional methods are also provided to make working with these matrices easier. Some of the more common methods are
translate(tx:Number, ty:Number) : Void

scale(sx:Number, sy:Number) : Void

rotate(angle:Number) : Void

identity() : Void

Other methods and their descriptions, as well as more information about the Matrix class can be found in Flash help. One method you may not find available is a skew() method. Since skewing is a little atypical of normal transformations, no method is provided. It can be implemented manually through adjusting the b and c properties of a matrix instead.
Each of the methods mentioned above operate on and alter the matrix from which they are called; they do not return a new transformed matrix. Here is a basic rundown.

translate

translate(tx:Number, ty:Number) : Void
The translate method simply moves a transformation by tx and ty. This process is additive so the tx and ty passed to translate is added on to any existing value of tx and ty in the matrix.
my_matrix.translate( 5, 10 );
is the same as
my_matrix.tx += 5;
my_matrix.ty += 10;

scale

scale(sx:Number, sy:Number) : Void
The scale method scales a transform matrix by an sx amount in x and an sy amount in y. These values are multiplied so a value of 1 represents no scale. One thing to understand about scale, and this applies to rotate as well, is that the values used also affect the matrix's tx and ty properties affecting the transform's position.
my_matrix.scale( 1.5, 2 );
is the same as
my_matrix.a *= 1.5;
my_matrix.b *= 2;
my_matrix.c *= 1.5;
my_matrix.d *= 2;
my_matrix.tx *= 1.5;
my_matrix.ty *= 2;

rotate

rotate(angle:Number) : Void
The rotate method rotates a transform matrix by angle amount where angle is measured in radians. As with scale, rotation is not only applied to the a, b, c, and d properties that affect rotation, but tx and ty as well. The math behind rotation is also a little more complex, as you might have guessed.
my_matrix.rotate( Math.PI/4 );
is the same as
var sin = Math.sin( Math.PI/4 );
var cos = Math.cos( Math.PI/4 );
var a = my_matrix.a;
var b = my_matrix.b;
var c = my_matrix.c;
var d = my_matrix.d;
var tx = my_matrix.tx;
var ty = my_matrix.ty;
my_matrix.a = a*cos - b*sin;
my_matrix.b = a*sin + b*cos;
my_matrix.c = c*cos - d*sin;
my_matrix.d = c*sin + d*cos;
my_matrix.tx = tx*cos - ty*sin;
my_matrix.ty = tx*sin + ty*cos;

identity

identity() : Void
The identity method converts any matrix into an identity matrix no matter what the prior transformation. In essence, this removes all transformations from the matrix from which it's called.
my_matrix.identity();
is the same as
my_matrix.a = 1;
my_matrix.b = 0;
my_matrix.c = 0;
my_matrix.d = 1;
my_matrix.tx = 0;
my_matrix.ty = 0;

Movie Clip Matrices

When working with movie clips, you have access to the transform matrix affecting the movie clip through the matrix property of that movie clip's transform object.
var my_matrix = my_mc.transform.matrix;

This matrix is actually provided as a copy of the "real" matrix being applied to the movie clip. What this means is that if you attempt to alter properties of that matrix directly, they will not be reflected in the transformations applied to the movie clip. Instead, you would need to work from a copy and then re-assign that altered copy back to the matrix property of the transform object for it to be applied.
my_mc.transform.matrix.translate(5, 0); // no change

var my_matrix = my_mc.transform.matrix;
my_matrix.translate(5, 0);
my_mc.transform.matrix = my_matrix; // changes my_mc's position
Interact with this movie clip and see how each method affects it when the matrix operations are called on the movie clip's transform matrix.


Note:

Like many other of the new classes bundled with Flash 8, the Matrix class has a clone() method which allows you to easily create a copy of an existing matrix. Matrices accessed from a movie clip's transform object are automatically cloned.
When a movie clip is a child of another movie clip and both movie clips have transformations applied to them, the resulting visuals of the child movie clip appear as a combination of its own transforms with those applied by its parent.

Matrix Multiplication

Matrices are much like complex numbers. You can perform common number operations such as addition and even multiplication. Multiplication, in particular, is an important operation when dealing with transform matrices. Matrix multiplication is what is used to apply the transformations specified in transformation matrices. In fact, the formulas previously mentioned for deriving x' and y' from a matrix is a result of matrix multiplication on a point or row vector.

A row vector is an 1 x n matrix - a single row matrix of n values. A vector often represents a point in a 2D or 3D space. For our purposes, a vector is a 1 x 3 matrix consisting of values x, y, and the number 1 representing a point in 2D space in Flash.

Though x and y are the only important values in this vector, the 1 is still necessary much in the same way u, v, and w are in a transform matrix.
Such a vector can be multiplied by a transformation matrix to have that transformation applied to the point it represents. With matrix multiplication, however, it is required that the first matrix in the operation have a number of columns equal to the number of rows in the second matrix . Since a vector here is 1 x 3 and the transformation matrix 3 x 3, this requirement is met with row vector on the left side of the equation.


The reason for this requirement revolves around how matrix multiplication is evaluated. In matrix multiplication, the resulting matrix is an m x n matrix where m is the number of rows in the first matrix and n is the number of columns in the second. This requirement also makes order important. For example, given two matrices A and B, A*B does not always equal B*A. There are situations where that is the case, and you'll see some of that later on.

Each new value in the resulting matrix is a summation of the products of the values that correspond to the first matrix's columns with the second matrix's rows. For example, given a matrix * vector multiplication, the first value in the resulting vector would be

x*a + y*c + 1*tx
Doing the same for each row and its respective column in the vector gives the vector

or

You'll notice that this results in the same formula seen before used to evaluate x' and y'.

x' = x*a + y*c + tx

y' = x*b + y*d + ty

Note:

When using a matrix of the alternative orientation, multiplication is an operation that is handled a little differently. Instead of using row vector * matrix, you would use matrix * column vector. A column vector is just like a row vector only written as a column in the form of a m x 1 matrix.


The end result is remains the same, only a it exists as a column vector instead of a row vector.
Vectors are commonly used in matrix multiplication to find a new point resulting from an applied transformation. But matrices can also be multiplied by other matrices to create a new transformation matrix that combines the transformations of those multiplied. This is the same process used in determining a new transformation of a child movie clip when both itself and its parent have transformations applied to them.
Consider 2 transformation matrices to be multiplied.

Since the first has columns equal to the number of rows in the second, multiplication is possible. The same method used with multiplication with the vector is used here only some additional columns are provided by the second matrix that need to be considered in the calculation.

After each row and column as been multiplied and added, you get the following




which reduces to


You can see that this continues to follow the same style of 3x3 transformation matrices where u, v, and w are 0, 0, and 1.
We can now apply this to a simple example. Here are two transformation matrices, one which scales x by 200% and one which skews y by a factor of 1.



In the resulting transformation matrix, the skew factor has been multiplied by 2.
Now lets see what happens when the order of the matrices are switched. Do you think the result will be the same?



The results are, in fact, not the same. The scaling is no longer being applied to the skew, but has instead simply been included with it.

Note:

Remember any matrix multiplied by the identity matrix will result in no change of the original matrix.
Don't be worried if a lot of this seems overwhelming. You don't really need to know how matrix multiplication works. In fact, Flash's Matrix class provides methods for performing these operations for you, both on points (transformPoint()) as well as matrices (concat()). Chances are you will never have to manually perform multiplication as see above. Nevertheless, knowing how it works can help provide a better overall understanding.
import flash.geom.Matrix;

var scale_matrix, skew_matrix;

scale_matrix = new Matrix(2, 0, 0, 1, 0, 0);
skew_matrix = new Matrix(1, 0, 1, 1, 0, 0);
skew_matrix.concat(scale_matrix);
trace(skew_matrix); // (a=2, b=0, c=2, d=1, tx=0, ty=0)

scale_matrix = new Matrix(2, 0, 0, 1, 0, 0);
skew_matrix = new Matrix(1, 0, 1, 1, 0, 0);
scale_matrix.concat(skew_matrix);
trace(scale_matrix); // (a=2, b=0, c=1, d=1, tx=0, ty=0)

Like translate, scale, rotate, and identity, concat also alters the current matrix instance as opposed to return a new matrix.
When multiplying with row vectors, Flash point instances can be used with a matrix's transformPoint command.
import flash.geom.Matrix;
import flash.geom.Point;

var scale_matrix, original_point, scaled_point;

scale_matrix = new Matrix(2, 0, 0, 1, 0, 0);
original_point = new Point(10, 10);
scaled_point = scale_matrix.transformPoint(original_point);
trace(scaled_point); // (x=20, y=10)
Notice that with transformPoint, a new, transformed point is returned. Also notice that the order in which the multiplication is written in Flash using either concat or transformPoint is opposite that written when using matrices. For example given two matrices A and B and a point P

A*B -> B.concat(A);

P*A -> A.transformPoint(P);

In terms of the parent-child movie clip relation with matrix multiplication, you have
Child.concat(Parent);

Concatenated Matrices

Lets say we have 2 movie clips, the first of which is a child of the second. Take the first, child movie clip and skew it along x by a factor of 1. Then, for the second, parent movie clip, scale it along x by 200%. The resulting appearance of the child movie clip from the main timeline is a movie clip that appears to be both scaled and skewed. This same appearance can be duplicated by a single clip not nested within a transformed parent. The transform matrix of such a clip would equal that of the original child movie clip's transform matrix multiplied by the transform matrix belonging to it's parent.


A parent movie clip's transform matrix is used in matrix multiplication to further alter the transformations of its children. Keep in mind that the actual matrix associated with a child movie clip does not contain these changes. It remains unique to that movie clip and contains only the transformations applied to it directly, not any of those that its parent or any other parent movie clips may be adding on to that. Flash does, however, provide an additional property in a movie clip's transform object that provides all transforms from all parents in the form of a single matrix. This is the
concatenatedMatrix property. It represents the result of multiplication of all the matrices affecting a nested movie clip.
var parent_matrix = parent_mc.transform.matrix;
var child_matrix = parent_mc.child_mc.transform.matrix;
var childconcat_matrix = parent_mc.child_mc.transform.concatenatedMatrix;

child_matrix.concat(parent_matrix);

trace(child_matrix); // (a=2, b=0, c=2, d=1, tx=0, ty=0)
trace(childconcat_matrix); // (a=2, b=0, c=2, d=1, tx=0, ty=0)
You can think of the concatenatedMatrix property being to matrices what globalToLocal is to points, it provides the transformations needed to match that of the concatenated transformation of the targeted matrix. Using a concatenated matrix, you can transform a movie clip in the main timeline to match the transformation of a nested movie clip with multiple transforms applied by multiple parents.

Inverse Matrices


You also have the capability of removing all transformations from a nested movie clip to make it seem as though it is not being transformed at all. The concatenated matrix alone, however, will not provide this for you. What you need is an inverse matrix.
An inverse matrix is a square matrix where there exists another unique matrix that, when multiplied with the inverse, results in the identity matrix. Both matrices are then considered invertable and are inverses of each other. All Flash transformation matrices are invertable meaning for each transformation matrix, there exists another matrix that when multiplied by the transformation matrix will give you the identity matrix. Given the identity matrix I and a matrix A, there exists a matrix B so that

A*B = I
and
B*A = I
The method of obtaining an inverse matrix manually is a little complex. It involves finding the adjoint of the matrix and dividing it by its determinant. The process is slightly simpler given the form of our affine transformation matrices but the details of which is still beyond the breadth of this tutorial. It reduces to the following.
Given the matrix

its inverse can be found using

As with matrix multiplication and the concat method, the Matrix class in Flash is able to provide a method that makes life a bit easier in finding inverse matrices. Using the invert() method, you can easily convert a matrix into its inverse with minimal hassle.

import flash.geom.Matrix;

var my_matrix = new Matrix(2,3,5,7,2,4);
trace(my_matrix); // (a=2, b=3, c=5, d=7, tx=2, ty=4)

my_matrix_inverse = my_matrix.clone();
my_matrix_inverse.invert();
trace(my_matrix_inverse); // (a=-7, b=3, c=5, d=-2, tx=-6, ty=2)

my_matrix_inverse.concat(my_matrix);
trace(my_matrix_inverse); // (a=1, b=0, c=0, d=1, tx=0, ty=0)
As seen above, multiplying the inverse by the original matrix results in the identity matrix.
Using an inverse matrix, a movie clip can have all transformations from all parent movie clips removed by multiplying its current matrix by the inverse of its concatenated matrix.
var concat_matrix = parent_mc.child_mc.transform.concatenatedMatrix;
concat_matrix.invert();
concat_matrix.concat(parent_mc.child_mc.transform.matrix);
parent_mc.child_mc.transform.matrix = concat_matrix;

Manipulating Transformation Matrices

Now that most of the basics of transformation matrices has been covered, its about time that some of this knowledge is put to use. It has only been with Flash 8 that now, through ActionScript, we can manipulate movie clips as easily as you could in the Flash IDE
(Integrated Development Environment), all thanks to transform matrices.
First we can work with what we know. The basic methods for matrix transformation are translate, scale, and rotate. If you've forgotten, there is no skew. How about we change that?

In order to make a custom skew method that functions like the other methods, you would need to consider that the skew be applied on top of the other transformations of the matrix including translation. If you attempted to set the skew properties (b and c) of a matrix that wasn't the identity matrix directly, it is possible that, given whatever transformations currently exist within the matrix, you could corrupt the transformation beyond a simple skew. Luckily, matrix multiplication is a process that would apply one transformation to another on top of any transformations that already existed within the original matrix. That means adding a simple skew is just a matter of multiplying an existing matrix by a skewed identity matrix.
function skew(matrix, x, y){
matrix.concat( new flash.geom.Matrix(1, y, x, 1, 0, 0) );
}
This simple skew function uses concat with a new identity matrix whose c and b values are set to the x and y values passed. As a result, the original matrix is multiplied by the new skewed matrix skewing it appropriately regardless of any prior transformations. Like translate, scale, and rotate, this skew function also affects the current translation properties of the matrix. The only difference here is that, since this skew method is not part of the Matrix class in Flash, its usage requires that the target matrix be passed as an argument.

skew(my_matrix, 1, 0);
One thing you'll notice about methods like scale (and this new skew method) is that transformations applied using these are not based around the current transforms of the matrix to which they are applied. They take into account the preexisting transformations, but don't base their scale or skew on those transformations. To more clearly demonstrate what I'm talking about, consider a movie clip rotated 45 degrees. When considering a scale being applied to this clip, there are conceptually two possible outcomes; scaling as though there were no rotation or scaling based on the rotation.

Using scale and the other Matrix class methods, you get scaling on top of that rotation as though there was no rotation as seen in the first variation, not that as shown in the second. If you wanted scaling to work with the rotation, like seen in the second, you'd actually want scaling to be applied before the rotation. Think about it in terms of the parent-child relationship; when the child movie clip is scaled, the scaling is in line with the rotation of the parent. This is contrary to scaling applied by the scale method which acts more like a rotated child being scaled by the parent. The matrix transform methods work as parent transformations adding to the existing children. To get the opposite affect, all you need to do is use matrix multiplication but change the order of in which the matrices are multiplied.

For this switch-around, you'll need to start with the method's transformation and then multiply in the original transformation on top of that. For the starting matrix, you simply use the desired method on an identity matrix. With that, we can create new methods that affect "inner" transformations.
function innerScale (matrix, x, y){
var scale_matrix = new flash.geom.Matrix();
scale_matrix.scale(x, y);
scale_matrix.concat(matrix);
return scale_matrix;
}

function innerSkew (matrix, x, y){
var skew_matrix = new flash.geom.Matrix();
// assume skew function for matrices is defined
skew(skew_matrix, x, y);
skew.concat(matrix);
return skew_matrix;
}

function innerRotate (matrix, angle){
var rotate_matrix = new flash.geom.Matrix();
rotate_matrix.rotate(angle);
rotate_matrix.concat(matrix);
return rotate_matrix;
}
Take notice that these methods actually return a matrix instead of altering the original. For the purposes of these examples, it was just easier to that. Here's how one could be applied to a movie clip.
var my_matrix = my_mc.transform.matrix;
my_matrix = innerScale(my_matrix, 2, 1);
my_mc.transform.matrix = my_matrix;
In using these transformations, you probably noticed that translation was not affected. This is because the base transformation actually had no translation, so whatever transformation was reapplied from the original matrix just resulted in using the original translation values from that matrix.
What if, however, you don't want translation to be affected in the original methods as well? Flash actually already provides such a method that ignores translation when translating points. It's the deltaTransformPoint() method and it acts just like the transformPoint method except that transformations are not applied to the translation properties. Other matrix transform methods do not have similar counterparts, but you could easily provide that functionality simply by storing the original location of a matrix prior to transformation and just reassign those values afterwards. That's right, no complicated matrix operations involved.

function deltaScale (matrix, x, y){
var position = new flash.geom.Point(matrix.tx, matrix.ty);
matrix.scale(x, y);
matrix.tx = position.x;
matrix.ty = position.y;
}

function deltaSkew (matrix, x, y){
var position = new flash.geom.Point(matrix.tx, matrix.ty);
// assume skew function for matrices is defined
skew(matrix, x, y);
matrix.tx = position.x;
matrix.ty = position.y;
}

function deltaRotate (matrix, angle){
var position = new flash.geom.Point(matrix.tx, matrix.ty);
matrix.rotate(angle);
matrix.tx = position.x;
matrix.ty = position.y;
}
These methods, like the original transform methods, but unlike the inner methods, transform the values within the matrix in which they are used instead of returning a new matrix.
Alternatively you could manually apply the transformations to each property of a matrix manually as outlined in the definitions of the original methods, but it's usually easier to just save and reassign the last translation values, especially for operations like rotation where the calculations can be a bit extensive.
function deltaRotate (matrix, angle){
var sin = Math.sin( angle );
var cos = Math.cos( angle );
var a = matrix.a;
var b = matrix.b;
var c = matrix.c;
var d = matrix.d;
matrix.a = a*cos - b*sin;
matrix.b = a*sin + b*cos;
matrix.c = c*cos - d*sin;
matrix.d = c*sin + d*cos;
}

Transformation Conversions

Sometimes you may need to compare transformation matrix values with those that exist in the Flash IDE or to those used in more generic ActionScript properties. Transformation matrix values, however, do not always correlate with their other Flash counterparts. Translation, for instance, relates directly to those values expressed as x (_x) and y (_y) position in Flash, but scale, skew, and rotation are handled slightly differently.

translation


Translation is, for the most part, the easy one. The tx and ty properties in a matrix directly relate to the _x and _y properties provided by ActionScript to reflect a movie clip's position within it's parent timeline. The values present in the Flash IDE in the property inspector, however, can differ.
The Flash IDE allows for position to be based on two separate locations. That of the top left of the movie clip or that of the movie clip's center. The option of using either is presented in the coordinate grid of the info panel

This center option does not always represent the local 0,0 location, or origin, of the movie clip in question, though. It's actually related to the transformation center point provided by the transform tool and is represented as a small black and white circle in Flash. By default this is placed in the center of a movie clip instance but can be adjusted using the transform tool. In order for translation values, or even _x and _y for that matter, to match up with this transformation center point, it would need to be placed on the origin of the movie clip which is represented by a black and white cross.

The transformation center point is not accessible by ActionScript, so keep that in mind as you are working with movie clips in Flash. It is often best to keep the registration point aligned with the movie clip's origin so you have a direct relation with the values you see in the Flash IDE and those accessible through ActionScript.

var my_matrix = my_mc.transform.matrix;

trace("x: " + my_matrix.tx);
trace("y: " + my_matrix.ty);

scale

Scale mostly relates directly to the a and d properties of a transformation matrix but is complicated by the effects of skewing. Without skewing, the a and b properties directly relate to the scale properties presented by flash - those in the IDE's transform panel and those given by _xscale and _yscale in ActionScript - with the simple exception of a matrix's scale being based on 1 while Flash bases scale on 100 for a scale of 100%.
When skewing is involved, the scale of an axis changes as it continues to stretch based on the relationship to the other axis, either x to y or vice versa. Because of these relations, its only a matter of using Pythagoreans theorem to acquire the correct scale factor


var my_matrix = my_mc.transform.matrix;

trace("x scale: " + Math.sqrt(my_matrix.a * my_matrix.a + my_matrix.b * my_matrix.b));
trace("y scale: " + Math.sqrt(my_matrix.c * my_matrix.c + my_matrix.d * my_matrix.d));

skew

Prior to transformation matrices in Flash 8, skew values were not accessible through ActionScript. The Flash IDE, however, did, and still does, provide values for skew in the transform panel in the form of values of rotation (in degrees). This is slightly different than the values used to interpret this transformation in the actual transform matrix. Values there represent a ratio by which one axis scales according to the other. They are not rotation or angle values.
The rotation values given by Flash represent the angles created on the opposite axis as a result of that axis being skewed. For example, skewing the x axis creates an angle between the now tilted y axis and its original vertical orientation.

Depending on the amount of skew, this angle varies. Using an arbitrary point along either axis and transforming it with a movie clip's matrix will allow us to obtain the value of this rotation using arctangent. An additional 90 degree offset is needed with x skew compensate for the orientation of the y axis.
var my_matrix = my_mc.transform.matrix;

var px = new flash.geom.Point(0, 1);
px = my_matrix.deltaTransformPoint(px);
var py = new flash.geom.Point(1, 0);
py = my_matrix.deltaTransformPoint(py);

trace("x skew: " +((180/Math.PI) * Math.atan2(px.y, px.x) - 90));
trace("y skew: " +((180/Math.PI) * Math.atan2(py.y, py.x)));

rotation

If you know skew, you know rotation. Flash uses the x skew angle for rotation.

var my_matrix = my_mc.transform.matrix;

var px = new flash.geom.Point(0, 1);
px = my_matrix.deltaTransformPoint(px);

trace("rotation: " +((180/Math.PI) * Math.atan2(px.y, px.x) - 90));

Applications

With the basics down, its time that matrices can be put to work in some (somewhat) real-world applications of this knowledge, both in manipulating movie clips and for use in BitmapData operations.
Shaking Smilies

Here, a group of smiley movie clips are wildly distorted within a couple of nested, transforming movie clips. When clicked, each will appear to break out of the transformations of its parents and present itself undistorted to the user by using invert with concatenated matrices.

[ view | download ]

As previously demonstrated, a nested, transformed movie clip can be fairly easily taken out of its transformations using invert and a concatenated matrix. This example does that but adds in the animation of the movie clip transforming from its original transform to that of the new, inverted transform. It does this using a custom matrixInterpolate() method.
The Point class in Flash has an interpolate() method that allows you to find any point along the line connecting two other points. Basically, this is a tween method that finds those "in-between" values. The Matrix class does not have such a method, so one was created for this example. All it does is return a new matrix with values in between each of the properties of two other matrices given a value t which is between 0 and 1.
function matrixInterpolate(m1, m2, t){
var mi = new flash.geom.Matrix();
mi.a = m1.a + (m2.a - m1.a)*t;
mi.b = m1.b + (m2.b - m1.b)*t;
mi.c = m1.c + (m2.c - m1.c)*t;
mi.d = m1.d + (m2.d - m1.d)*t;
mi.tx = m1.tx + (m2.tx - m1.tx)*t;
mi.ty = m1.ty + (m2.ty - m1.ty)*t;
return mi;
}
Combining this with an onEnterFrame event, the smilies can animate from their original, nested transforms to the inverted transform and back again.

One thing about the inverted transform, however, is that it is not just an inverted concatenated matrix. Just inverting it would make it an identity matrix and throw the movie clip to position 0,0 with normal scale (small for the smilies in this example). Instead, another matrix is combined with the resulting inverted identity to place the selected smiley in the location on the right at a large scale.
Mouse Walking on the Floor

This example shows how a transform matrix can be used with beginBitmapFill() distort a a tiled image (used for the floor) as it shifts up the screen and an equally distorted mouse movie clip appears to walk on it. Additionally, it shows how an object (can of cheese) can be moved along with the transformed floor.

[ view | download ]

The following image is used for the tiled floor in this example.

Using beginBitmapFill, it will be drawn in a square that is sized to be with width and height of the movie (300 x 300). For the skewing effect, a matrix is used with beginBitmapFill to apply a skewed transformation that changes based on the mouse's x location.
When dealing with matrix transformations in beginBitmapFill, as with any bitmap operation, the "center" of the transformation will be located at the upper left of the bitmap being used. In this example, the center of the transformations is desired to be in the center of the movie. Using translate, that center can change from the upper left to the center of the movie. Because beginBitmapFill will tile the image being drawn, no imagery is lost as a result of the change in position. Instead, you just get a shift which may or may not even be initially evident. In applying a skew, however, the difference becomes more obvious.

You'll have to wonder, if translating centers the point of origin for the skew, how does the floor appear to be moving? Wouldn't that relate to translating? In fact, it would, but not with that beginBitmapFill. Two drawings with beginBitmapFill are actually used to get the effect of the floor. One is used center and skew the floor, and the other, drawn beforehand, is used to alter the original bitmap to shift its graphics by the amount of movement needed - translating it. This altered bitmap is then used as the bitmap drawn into the skewed floor

With that, the floor appears to move correctly regardless of the skew and always from the center of the movie.
The other elements in the movie are the mouse and a can of cheese. The mouse is simply placed at the center of the floor and set to match the skew applied to the floor. This transforms it with the floor.
The cheese is a little different. It actually doesn't have any transformations applied to it. This is because it is actually sticking straight up as opposed to laying down on the floor. If on the floor it would shift with the floor, but since the (perceived) vertical axis does not change, neither does the can of cheese. It does, however, need to move with the floor.

As the cheese moves vertically with the floor at the same level of shifting applied to the original tile bitmap, it will need to make sure that horizontally it remains at the correct location. This location will vary based on the amount of skew as well as its distance from the center of the skew - the center as placed by the translation of the skewed beginBitmapFill. In fact, when vertically positioned with that center, the horizontal position is not affected by the skew at all. Only incrementally from that position does the skew affect it. What you end up getting is a formula that looks something like this:
cheese_x_offset = center_x + (cheese_y - center_y) * skewAmount;
As the difference between the cheese's y position and the y center, the amount of skew affects it more making the offset of the cheese from the x center increasingly greater.
Black Hole

By rotating and scaling a matrix used in the BitmapData's draw() method, the effect of a black hole can be created, sucking in and enveloping all imagery seen on the screen.

[ view | download ]

There are 3 kinds of transformations applied to the matrix causing the black hole effect, rotation, scale and translation. Rotation gives the swirling effect, scale makes the graphics scale down and sink inward, and translation makes sure it's all centered within the screen. The bitmap representing the black hole continues to, not only draw the fountain of stars emitting from the position of the cursor, but also its last graphical appearance which gives the effect of the trail that eventually gets sucked into the transformations
Rotation and scaling are pretty straightforward, but when it comes to translation, some extra effort is needed to make sure that translation is actually correct to take in account not only scaling but also rotation. Remember, the center of a bitmap matrix is in the upper left. This black hole effect is centered in the middle of the bitmap/screen. This is handled is through a multi-step process that involves scaling, centering based on the scale, rotating, and repositioning.
1. First, the matrix is scaled. 2. Then, based on that scale, the matrix is translated to position it's center at 0, 0 (center is based on the bitmap it will be affecting).
3. From that position it is rotated. Because of the previous shift in translation, rotation is based around the center. 4. Finally, the matrix is translated back so that its center is centered within the effect.

3D Picture Cube

The classic rotating cube using http://www.senocular.com/flash/tutorials/transformmatrix/images for its sides. Thanks to Flash 8 and having access to a movie clip's transform matrix, this example becomes much simpler to implement.

[ view | download ]

Rotating cubes of http://www.senocular.com/flash/tutorials/transformmatrix/images like these have been around since Flash 5, and maybe even before that. The idea behind this effect is transforming movie clips so that they match the sides of a cube being rotated in a 3D space (sans perspective). Before Flash 8, movie clip nesting was needed to get the transformations needed, notably in terms of skewing a movie clip. Now, however, with Flash 8, the effect is easier than ever to pull off thanks to developers being able to directly access a movie clip's transform matrix. In fact, once you get past the 3D, altering the transform matrix is nothing - no complicated equations or trigonometry needed. All you have to do is find the difference of position of some points making up the side of your cube and you pretty much have it.
Transform the following movie clip using 3 points to define the transformation and witness the obvious relationship between the difference of positions and the transformation matrix.

Source:
Author: Trevor McCauley
Source root: http://www.senocular.com/flash/tutorials/transformmatrix/

Reference:
http://s9.zetaboards.com/Ultimate3D_community/topic/7104235/1/
http://en.wikipedia.org/wiki/Transformation_matrix
http://en.wikibooks.org/wiki/OpenGL_Programming/3D/Matrices
http://stackoverflow.com/questions/850179/how-to-apply-a-transformation-matrix
http://www.kwon3d.com/theory/transform/transform.html
http://knol.google.com/k/matrices-for-3d-applications-translation-rotation#
http://wally.cs.iupui.edu/n351/3D/matrix.html
Labels: AS3   at:  7:09 PM     0   comments

Older Posts Home
Subscribe to: Posts ( Atom)
© Hung Le 2007-2016. Powered by Blogger