Entries Tagged 'actionscript' ↓

Dark Intellij 11 color scheme for actionscript

I recently upgraded Intellij from version 10 to 11. Jetbrains have upgraded he syntax colouring for actionscript and javascript in this version so it is now separated ( in version 10 it was combined). This is great except they never wrote an import script for bringing your actionscript colours from version 10 over to 11, if you try it you are are going end up with a hot mess. I’ve manually recreated what I had previously by hand. If you like dark scheme’s then download this one, you know what they say: once you go black you never go back.

as3dark.jar


Ant task to terminate Flash Player Debugger

I’ve just switched over to IntelliJ as my actionscript editor. The IDE is great, really fast with some great features. Check out the review over at Flash magazine.
They only recently introduced actionscript support so its still kind of light on customisation for developing with the Flash platform. One thing that was driving me nuts is that when you debug a swf it always opens in a new window. There is no close previous player or terminate process. However this easy enough to achieve with an Ant script. Add the following to your build script and then in the project debug configuration, choose run Ant script before launch.

<target name="closeDebugger">
		<exec executable="killall">
		    <arg line="-9 'Flash Player Debugger'" />
		</exec>
	</target>

This will kill all the Flash Player’s that are open. Its pretty dirty but it works well. This is a unix command, so will only work on Mac or on a Pc with Cygwin installed.


Away3D BezierPatch

image warp

I’ve been playing around the BezierPatch primitive in away3D recently. It works in a similar way to the bezier surface i created. Its quite easy to create some very interesting effects. The source for this is on wonder.fl so fork it and make it your own.

BezierPatch away3D – wonderfl build flash online


Warping Bitmaps with a Bezier Surface

image warp

If you have read my previous posts on drawTriangles, you will see that I love warping images. I decided to take this a bit further by using a Bezier surface. A bezier surface or bezier patch can warp a grid by using a set of control points. The control points in this example are the red circles, the grid can be seen by clicking the show grid checkbox. Try dragging the controls points to create your own warp or just sit back and watch the show.
There is also a method for doing this using away3d plus checkout this 3d surface built using nurbs.

This movie requires Flash Player 10

Update:
You can view the bezier surface in action on this client project I worked on recently. The surface was used to create chewing mouth animations from user’s facebook photos.


Drawing a dashed line using the AS3 drawing API

image warp

I was surprised recently to learn that the actionscript drawing api did not include a dashed-line style in the options. Well not to worry, drawing a dashed line is fairly straightforward. You just need to calculate the distance between each drawing points and divide it by the gap space. Then use a loop to draw multiple lines between the points, toggling the alpha to 0 or 1 on each iteration. Its not pixel perfect or anything, but its a relatively painless solution.

Checkout the example below to see it in action.

Dashed Line

This movie requires Flash Player 10

source

package {
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;

	/**
	 * @author Phil
	 */
	public class DashedLine extends Sprite {
		private var _lineThickness : Number = 1;
		private var _lineColor : uint = 0xFFFFFF;
		private var _dashSpace : Number = 5;

		public function DashedLine() {
			stage.align = StageAlign.TOP_LEFT
			stage.scaleMode = StageScaleMode.NO_SCALE
			graphics.beginFill(0x000000, 1)
			graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight)
			graphics.endFill();
			var data : Array = getPoints()
			var px : Number;
			var py : Number;
			var draw : Boolean = true;
			// main drawing loop
			for(var i : int = 0;i < data.length;i++) {
				var x : Number = data[i][0]
				var y : Number = data[i][1]
				if(i == 0) {
					graphics.moveTo(x, y)
				} else {
					var dx : Number = x - px;
					var dy : Number = y - py;
					var distance : Number = Math.sqrt(dx * dx + dy * dy);
					// calculate the number of dashed to draw based on the distance between each point
					// always draw at least 1 line
					var loops : int = Math.max(1, Math.floor(distance / _dashSpace))
					// dash drawing loop
					for (var j : int = 0;j < loops;j++) {
						var alpha : Number = draw ? 1 : 0; // toggle the alpha on and off for each dash iteration
						draw = !draw;
						graphics.lineStyle(_lineThickness, _lineColor, alpha)
						var a : Number = j / loops;
						graphics.lineTo(px + (dx * a), py + (dy * a))
					}
				}
				// complete the last line
				if(i == data.length - 1) {
					graphics.lineStyle(_lineThickness, _lineColor, 1)
					graphics.lineTo(x, y)
				}
				// save the previous position
				px = x
				py = y
			}
		}

		public function getPoints() : Array {
			var points : Array = [];
			points.push([100,300]);
			points.push([78.8,168.43990319999997]);
			points.push([88.64999999999999,167.8654816]);
			points.push([98.5,161.76375440000004]);
			points.push([108.35,159.4435878]);
			points.push([118.2,157.12367460000002]);
			points.push([128.05,161.7856192]);
			points.push([137.9,157.13815460000004]);
			points.push([147.75,150.45462099999997]);
			points.push([157.6,150.170813]);
			points.push([167.45,154.25098739999999]);
			points.push([177.29999999999998,151.93103799999997]);
			points.push([187.14999999999998,153.9744918]);
			points.push([197,153.4000702]);
			points.push([206.85,110.37080679999997]);
			points.push([216.7,130.17818400000002]);
			points.push([226.55,134.694658]);
			points.push([236.4,142.08358819999995]);
			points.push([246.25,138.89092920000002]);
			points.push([256.1,135.9892458]);
			points.push([265.95,133.0872366]);
			points.push([275.8,128.14915839999998]);
			points.push([285.65,123.79263320000001]);
			points.push([295.5,119.7267578]);
			points.push([305.35,117.2756667324]);
			points.push([315.2,50.82457562860003]);
			points.push([325.05,70.35882340200001]);
			points.push([334.9,90.44433818999997]);
			points.push([344.75,106.4859321994]);
			points.push([354.59999999999997,107.48357411719999]);
			points.push([364.45000000000005,106.0178218906]);
			points.push([374.29999999999995,104.05938458700001]);
			points.push([384.15000000000003,99.6382731932]);
			points.push([394,96.6944970124]);
			points.push([403.85,95.22874478580002]);
			points.push([413.7,92.77765371819999]);
			points.push([423.55,90.81921641459996]);
			points.push([433.4,87.87544023380002]);
			points.push([443.25,84.93169536599999]);
			points.push([453.1,84.94396709360001]);
			points.push([462.95,81.50750583580003]);
			points.push([472.8,77.08570573699996]);
			points.push([482.65,73.64924447920004]);
			points.push([492.5,69.22744434420002]);
			points.push([502.34999999999997,66.28369947639999]);

			points.push([502.34,300]);
			points.push([100,300]);
			return points;
		}
	}
}

Flash 10 drawTriangles

image warp

Adobe introduced some new functions in the flash 10 drawing api for 3d support. One of them is drawTriangles. This enables bitmaps to be drawn to a 3d mesh. But it can also be used in 2d for skewing and warp effects. In a nutshell it allows you to define a shape and then map points of a bitmap to this shape. Click on the examples below to see the points of the rectangle warp to new positions. Here I’m defining the five points which make up the triangles and tweening the outside corners. The number of triangles and possibilities are infinite. This is great alternative to the infamous flash ide shape tween.
You can find some even better examples on wonder.fl. Just try searching for drawTriangles. Two of my favs are wonderwall and genie effect.

Random Warp

Bezier Minimise

This movie requires Flash Player 10

source for random warp

var _vertices:Vector.<Number >  = new Vector.<Number >   ;
var _indices:Vector.<int >  = new Vector.<int >   ;
var _uvtData:Vector.<Number >  = new Vector.<Number >   ;
var _image:BitmapData = new Foxy();
var border:Number = 0;
var _width:Number = stage.stageWidth;
var _height:Number = stage.stageHeight;
//define the triangles
_vertices.push(0, 0);
_vertices.push(_width, 0);
_vertices.push(_width/2, _height/2);
_vertices.push(0, _height);
_vertices.push(_width, _height);
_indices.push(1, 0, 2);
_indices.push(0, 2, 3);
_indices.push(1, 2, 4);
_indices.push(2, 3, 4);

//define the bitmap mapping to triangle points
_uvtData.push(0, 0);
_uvtData.push(1, 0);
_uvtData.push(0.5, 0.5);
_uvtData.push(0, 1);
_uvtData.push(1, 1);

stage.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e=null):void
{

	var endVertices:Vector.<Number >  = new Vector.<Number >   ;
	endVertices.push(randNum, randNum);
	endVertices.push(_width-randNum, randNum);
	endVertices.push(stage.stageWidth/2, stage.stageHeight/2);
	endVertices.push(randNum, _height-randNum);
	endVertices.push(_width-randNum, _height-randNum);
	TweenMax.to(_vertices, 0.5, {endVector:endVertices, ease:Expo.easeOut, onUpdate:update});
}
function update():void
{
	graphics.clear();
	graphics.beginBitmapFill(_image);
	graphics.drawTriangles(_vertices, _indices, _uvtData);
	graphics.endFill();
}


source for bezier minimise

var _timeLine: TimelineMax;
var _vertices:Vector.<Number >  = new Vector.<Number >;
var _indices:Vector.<int >  = new Vector.<int >;
var _uvtData:Vector.<Number >  = new Vector.<Number >;
var _image:BitmapData = new Foxy();
var _width:Number = stage.stageWidth;
var _height:Number = stage.stageHeight;
//define the triangles
_vertices.push(startLT.x, startLT.y);
_vertices.push(startRT.x, startRT.y);
_vertices.push(startC.x, startC.y);
_vertices.push(startLB.x, startLB.y);
_vertices.push(startRB.x, startRB.y);
_indices.push(1, 0, 2);
_indices.push(0, 2, 3);
_indices.push(1, 2, 4);
_indices.push(2, 3, 4);

//define the bitmap mapping to triangle points
_uvtData.push(0, 0);
_uvtData.push(1, 0);
_uvtData.push(0.5, 0.5);
_uvtData.push(0, 1);
_uvtData.push(1, 1);

update();
function update():void
{
	_vertices[0]=startLT.x;_vertices[1]=startLT.y;
	_vertices[2]=startRT.x;_vertices[3]=startRT.y;
	_vertices[4]=startC.x;_vertices[5]=startC.y;
	_vertices[6]=startLB.x;_vertices[7]=startLB.y;
	_vertices[8]=startRB.x;_vertices[9]=startRB.y;

	graphics.clear();
	graphics.lineStyle(1, 0xFFFFFF);
	graphics.beginBitmapFill(_image);
	graphics.drawTriangles(_vertices, _indices, _uvtData);
	graphics.endFill();

}

stage.addEventListener(MouseEvent.CLICK, onClick);

function onClick(e=null):void
{

	if(_timeLine == null){
		var time:Number = 0.7;
		var ease:Function = Expo.easeInOut
		_timeLine = new TimelineMax({onUpdate:update});
		_timeLine.appendMultiple([
		TweenMax.to(startLT, time, {delay:0, bezierThrough:[{x:curveLT.x, y:curveLT.y}, { x:endLT.x, y:endLT.y}], ease:ease}),
		TweenMax.to(startRT, time, {delay:0, bezierThrough:[{x:curveRT.x, y:curveRT.y}, { x:endRT.x, y:endRT.y}], ease:ease}),
		TweenMax.to(startC, time, {delay:0, x:endC.x, y:endC.y, ease:ease}),
		TweenMax.to(startRB, time, {bezierThrough:[{x:curveRB.x, y:curveRB.y}, { x:endRB.x, y:endRB.y}], ease:ease}),
		TweenMax.to(startLB, time, {bezierThrough:[{x:curveLB.x, y:curveLB.y}, { x:endLB.x, y:endLB.y}], ease:ease})
		]);
	}else{
		if(_timeLine.reversed)
		_timeLine.play();
		else
		_timeLine.reverse();
	}

}

TextField fit to size

This is one function that should be in every flash developer’s toolbox. I’m so over adjusting textfields and font sizes to fit different lengths of content. There had to be better way I thought. How about a one size fits all solution. The function below uses a while loop to reduce the font size of the textfield one pt at a time until the text fits within the bounds of the width and height. Its almost too easy.

public static function fitToSize(txt : TextField, maxWidth:Number=-1, maxHeight:Number=-1) : void {
			var maxTextWidth : int = maxWidth &amp;gt; 0 ? maxWidth : txt.width;
			var maxTextHeight : int = maxHeight &amp;gt; 0 ? maxHeight : txt.height; 

			var f : TextFormat = txt.getTextFormat();

			while (txt.textWidth &amp;gt; maxTextWidth || txt.textHeight &amp;gt; maxTextHeight) {
				f.size = int(f.size) - 1;
				txt.setTextFormat(f);
			}
		}

Click on the stage below to view an example.

This movie requires Flash Player 10


Flash Catalyst project to SWC

Flash Catalyst. Its great isn’t it? Import your layout file and quickly create flex components. Catalyst exports a layout to a flex project file (FXP). In flash builder you can import this file as a new project. However I’ve found it is pretty tricky to import these new components into to an existing project because it requires alot of a refactoring or an additional source path.
I frequently use the export to swc feature within the Flash IDE to export my components into a flash builder project. It seemed strange that Adobe didn’t also include an export to swc feature in the latest flash builder. In order to export to a swc you need to use compc which is only accessible via the command line. Luckily you can use an ANT script to easily automate this task. If you don’t have ant installed for flash builder, follow the steps on this guide. Once installed you can use the script to below to build a SWC out of your flex skin project. You can then you this use this swc in other projects to apply the skin to existing components by using the skinClass property.

<project name="MySkin" default="compileSWC" basedir=".">
<property name="PROJECT_NAME" value="MySkin" />
<!-- change this line if your on a p.c. -->
<property name="FLEX_SDK" location="/Applications/Adobe Flash Builder 4/sdks/4.0.0/"/>
<property name="compc" location="${FLEX_SDK}/bin/compc"/>
<property name="mxmlc" location="${FLEX_SDK}/bin/mxmlc"/>
<property name="asdoc" location="${FLEX_SDK}/bin/asdoc"/>
<property name="SRC_DIR" location="src"/>
<property name="LIBS_DIR" location="libs"/>
<property name="RELEASE_DIR" location="bin-release/"/>
<property name="RELEASE_SWC" location="${RELEASE_DIR}/${PROJECT_NAME}.swc"/>
<property name="flashplayer" value="/SAFlashPlayer" />

<property name="FLEX_SDK_NAME" value="${FLEX_SDK}" />
	<target name="compileSWC">
					 <exec executable="${compc}">
					 	<arg line="-source-path '${SRC_DIR}' -library-path '${LIBS_DIR}' -target-player=10"  />
					 	<arg line="-output '${RELEASE_SWC}'" />
					 	<arg line="-is 'src'" />
					 	<arg line="-include-libraries 'libs'" />
					 	<arg line="-include-libraries '${FLEX_SDK}/frameworks/'" />
					 	<arg line="-include-libraries '${FLEX_SDK}/frameworks/libs/'" />
					 	<arg line="-include-libraries '${FLEX_SDK}/frameworks/locale/en_US/'" />
					 </exec>
			</target>
</project>

Box2D Ballooning

ballonscreen

Many of you may of seen Pixars recent movie UP. In the movie the main character manages to take flight in his house by attaching dozens of inflatable balloons to the roof. Seems a bit far fetched don’t you think? Obviously the guys at Pixar aren’t too concerned with the laws of physics.
Well here at fatlinesofcode we don’t mind if cartoons break the laws of physcis either. But we do love to test them.
I have built a fun prototype game in Box2D to test this house ballooning theory. The house is a box with multiple balls attached via distance joints. Each of the balls has an anti-gravitational force applied to it which provides lift to the house. To pilot this balloon the UP arrow key is used to simulate adding more hot air to the balloons. Each time you press it an upward force is applied to each balloon thus providing more lift to the house. Additionally the LEFT and RIGHT arrow keys can be used to apply left and right forces to the house. Combining these controls you can achieve steady flight. Check out the demo and try manoeuvring your balloon through the various obstacles.


Source here


Pixelated video effect [Part II]

space

I few weeks ago I posted a pixelation effect. I have since optimised the code and also added in support for webcam input.

Checkout the demo and source code below.

This movie requires Flash Player 10

Here is an explanation of the technique.

First get the bitmapData source from the video input. Then divide the data into a grid of new bitmaps using a double for-loop. Store each one these in a two dimensional array.

private function createBitmapGrid():void {

			var source:BitmapData = getVideoSource();

			var _w:Number=source.width;
			var _h:Number=source.height;
			var rows:Number=source.height/_divideGridBy; // cols
			var cols:Number=source.width/_divideGridBy; // rows
			var cellWidth:Number = _w/cols-_cellpadding;
			var cellHeight:Number = _h/rows-_cellpadding

			for (var i:uint=0; i<cols; i++) {
				for (var j:uint=0; j<rows; j++) {
					var tempBitmapData:BitmapData=new BitmapData(cellWidth,cellHeight, true, 0x000000);
					var tempBitmap:Bitmap =new Bitmap(tempBitmapData);
					tempBitmap.x=i*_w/cols;
					tempBitmap.y=j*_h/rows;
					if(! _particleArray[i])
					_particleArray[i] = {};
					_particleArray[i][j] = tempBitmap;
					_holder.addChild(tempBitmap);
				}
			} 			

		}

Then add an enterframe listener to update the all the bitmap cells in the grid. Add a double for-loop to go through each cell. Use the copyPixel function to copy a rectangular portion of the source image to each cell. After you copy the source data, find the average brightness of the cell and use it as a variable to adjust the z value of the bitmap cell.

this.addEventListener(Event.ENTER_FRAME, updateBitmapGrid);
private function updateBitmapGrid(e:Event):void {

			var source:BitmapData = getVideoSource();

			var _w:Number=source.width;
			var _h:Number=source.height;
			var rows:Number=source.height/_divideGridBy; // cols
			var cols:Number=source.width/_divideGridBy; // rows
			var cellWidth:Number = _w/cols-_cellpadding;
			var cellHeight:Number = _h/rows-_cellpadding

			for (var i:uint=0; i<cols; i++) {
				for (var j:uint=0; j<rows; j++) {
					var tempBitmap:Bitmap = null;
					if (_particleArray[i]) {
						if(_particleArray[i][j]){
							tempBitmap=_particleArray[i][j];
						}
					}
					if(tempBitmap != null){
						var p:Point = new Point(0, 0);
						var rect:Rectangle = new Rectangle(tempBitmap.x+_cellpadding, tempBitmap.y+_cellpadding, cellWidth, cellHeight);
						tempBitmap.bitmapData.copyPixels(source, rect, p);
						var color:Number=getAverageColour(tempBitmap.bitmapData);
						var brightness:Number=getBrightness(getAverageColour(tempBitmap.bitmapData));
						if(_moveZ)
						tempBitmap.z = 255 - (brightness * 1);

					}
				}
			}
		}
private function getAverageColour( source:BitmapData ):Number {
			var red:Number=0;
			var green:Number=0;
			var blue:Number=0;

			var count:Number=0;
			var pixel:Number;

			for (var x:Number = 0; x < source.width; x++) {
				for (var y:Number = 0; y < source.height; y++) {
					pixel=source.getPixel(x,y);

					red+=pixel>>16&0xFF;
					green+=pixel>>8&0xFF;
					blue+=pixel&0xFF;

					count++;
				}
			}

			red/=count;
			green/=count;
			blue/=count;

			return red << 16 | green << 8 | blue;
		}

		private function getBrightness(colour:Number):Number {
			var R:Number=0;
			var G:Number=0;
			var B:Number=0;

			R+=colour>>16&0xFF;
			G+=colour>>8&0xFF;
			B+=colour&0xFF;

			var br:Number=Math.sqrt(R*R*.241+G*G*.691+B*B*.068);
			return br;
		}

Download package