Affine Transformation in Flash 5 (ActionScript 1.0)

Sometimes you want more control over a movieclip than its position, size and transparency. These can be manipulated easily in ActionScript. What if you want to skew an image to the shape of a parallelogram? This kind of deformation is certainly trickier and requires nested movieclips.

Download Source File: Flash5_Affine_Transformation.zip

The innermost element is the image we want to distort. We place it inside a movieclip that itself is also inside a movieclip. The relationship with pseudocode:

Code:

movieclip {
	movieclip {
		image {}
	}
}

Now we can apply different transformation to the inner and outer movieclip. The three crosshairs represent the points that define the deformation of our parallelogram. Drag them around to see what happens. Finally some nice vector operations provide the solution for the scale and rotation values. You can use this technique to make a textured 3D cube in Flash 5.

Code:

MovieClip.prototype.parallelDeform = function(x1, y1, x2, y2, x3, y3) {

	/* calculate vectors
	*************************************/
	var x12 = x2 - x1;
	var y12 = y2 - y1;
	var x13 = x3 - x1;
	var y13 = y3 - y1;

	/* calculate parameters
	*************************************/
	var sig = (x12 * y13 - x13 * y12 >= 0) ? 1 : -1;
	var fi = sig * Math.acos( (x12 * x13 + y12 * y13) / Math.sqrt( (x12 * x12 + y12 * y12) * (x13 * x13 + y13 * y13) ) );

	/* apply transformation
	*************************************/
	this._x = x1;
	this._y = y1;
	this._xscale = 200 * Math.SQRT1_2 * Math.sin(fi/2);
	this._yscale = 200 * Math.SQRT1_2 * Math.cos(fi/2);
	this._rotation = 90 + (Math.atan2(y12, x12) + fi/2) * 180 / Math.PI;
	this.image._xscale = Math.sqrt(x13 * x13 + y13 * y13);
	this.image._yscale = Math.sqrt(x12 * x12 + y12 * y12);

}

MovieClip.prototype.updateGeometry = function() {

	/* get locator coordinates
	*************************************/
	var x1 = _root.c0._x;
	var y1 = _root.c0._y;
	var x2 = _root.cy._x;
	var y2 = _root.cy._y;
	var x3 = _root.cx._x;
	var y3 = _root.cx._y;

	/* rough check if locators moved
	*************************************/
	var sum = (x1 + y2) * (x2 + y3) * (x3 + y1);

	/* deformation unnecessary
	*************************************/
	if(this.checksum == sum) return;

	/* apply transformation
	*************************************/
	this.checksum = sum;
	this.parallelDeform(x1, y1, x2, y2, x3, y3);

}