Archive for category actionscript

Collection of useful links for working with Molehill

With the upcoming release of Molehill in a future version of Flash I decided to have a play around and see just what was involved in setting up a project in order to test out the new APIs. I was primarily interested in speed increased for 2D performance as this is the sort of work I do. Interestingly enough it seemed that using the 3D functionality for 2D sprites (using textures on simple square planes to work as sprites) didn’t offer any speed increase over normal blitting – having said that, normal blitting in the incubator build was lightning fast – much faster than the current player. Exciting times are ahead either way!

Here’s a list of the pages I used as reference while getting a basic understanding of the concepts involved for using Molehill:

Also – Don’t forget to set the wmode in the HTML file to direct!

Tags: ,

No Comments

Experimenting wtih Pixel Bender for Blitting in Flash

I’d been meaning to have a play around with Pixel Bender for a long while and finally got some time up my sleeve so decided that today was the day. What I was interested in wasn’t necessarily the image filtering razzle dazzle, but more trying to find out if there was a way to harness the much hyped speed increases presented by using Pixel Bender filters to do some of the processing that I currently use AS3 to do. As a Flash game developer, finding quicker and more efficient ways to render graphics and thus increase both the frame rate and number of intereactive objects on screen is like an obsession, and I thought it would be a good way to see if Pixel Bender could offer any benefits.

The short answer, unfortunately, is no. Clarifying a little bit, for my purposes, with the sort of games I create (2D blitted games) I found out that Pixel Bender performed slower than using copypixels, much slower – by a factor of 10!

Going in to a bit more depth, blitting is so far the most CPU efficient way of animating 2D graphics in Flash, that I know of at least. This means that I render all of my animations as spritesheets and then using copyPixels, I paste each frame of each sprite to the appropriate position on the game screen. I also animate the scrolling backgrounds in the same manner.

Having read a number of other blogs about Pixel Bender it was made apparent that creating instances of ShaderJobs is quite time consuming, and as each job is a once-only use object, you need to create one each frame cycle, for each blit operation. This starts to become extra worrying when you realise that if there are 10 characters on screen, that’s 10 blits, plus all of the other various animated items and the paralax background scrolls. So from the outset I was a bit warey, but decided to put it to the test by just blitting a background image. This of all the potential uses for Pixel Bender blitting I thought would provide the most advantage because of the fact that it is a single large bitmap, so perhaps the inherent speed of the Pixel Bender operation would outweight the cost of creating a FilterJob. Unfortunately, it didn’t.

For a loop of 10000 iterations the copyPixels operation took 1000 ticks whilst the Pixel Bender filter took 13825 – that’s over 10 times longer!

I think Pixel bender has a very specific and really obscure place. Great for doing complex, multi-stage processing on large media or datasets, but apart from that, the overhead of instantiation unfortunately dwarfs the speed benefit.

Here’s the Pixel Bender Filter Code:

<languageVersion : 1.0;>
 
kernel CopyPixel
<   namespace : "com.codeandvisual";
    vendor : "Code and Visual";
    version : 1;
    description : "Used to compare copy pixels to pixel bender";
>
{
    input image4 src;
    parameter float x_shift;
    parameter float y_shift;
    output pixel4 dst;
 
    void
    evaluatePixel()
    {
        float2 out_new = float2(outCoord().x+x_shift,outCoord().y+y_shift);
        dst = sampleNearest(src,out_new );
    }
}

And then the AS3 Project that was run to compare the two processes:

package 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Shader;
	import flash.display.ShaderJob;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import flash.utils.getTimer;
 
	/**
	 * ...
	 * @author james@codeandvisual.com
	 */
	public class Main extends Sprite 
	{
		[Embed(source="../filter/CopyPixel.pbj", mimeType="application/octet-stream")]
		protected var CopyPixel:Class;
		//
		[Embed(source="../images/image_1.png")]
		private var Image1:Class;
		//
 
		protected var loader:URLLoader
		protected var shader:Shader; 
		protected const TEST_LENGTH:int  = 10000
		protected var _source_data:BitmapData =  Bitmap(new Image1() as Bitmap).bitmapData
		protected var _output_data:BitmapData = new BitmapData(400,400,false,0)
		protected var _output_data_2:BitmapData = _output_data.clone()
 
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
 
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			initShader()
		}
		protected function initShader():void {
			var myTime:Number
			//
			shader = new Shader()
			shader.byteCode = new CopyPixel();
			//
			shader.data.src.width = _output_data.width;
			shader.data.src.height = _output_data.height;
			shader.data.src.input = _source_data;
			var myShiftX:Number
			var myShiftY:Number
			var t:int = 0
			//
			myTime = getTimer()
			for (t = 0; t < TEST_LENGTH; t++) {
				myShiftX = Math.random()*100
				myShiftY = Math.random()*100
				shader.data.x_shift.value=[myShiftX]
				shader.data.y_shift.value=[myShiftY]
				var shader_job:ShaderJob = new ShaderJob(shader, _output_data, _output_data.width, _output_data.height);
				shader_job.start(true);
			}
			addChild(new Bitmap(_output_data))
			trace("MY LENGTH FILTER = " + (getTimer() - myTime))
			//
			myTime = getTimer()
			for (t = 0; t < TEST_LENGTH; t++) {
				myShiftX = Math.random()*100
				myShiftY = Math.random()*100
				_output_data_2.copyPixels(_source_data,new Rectangle(myShiftX,myShiftY,_output_data_2.width, _output_data_2.height),new Point())
			}
			var myBitmap2:Bitmap = new Bitmap(_output_data_2)
			myBitmap2.x = _output_data.width
			addChild(myBitmap2)
			trace("MY LENGTH AS3 = " + (getTimer() - myTime))
 
		}
 
	}
 
}

You can download the source from here:
pixel_bender_blitting.zip

Further reading:
http://www.actionscript.org/resources/articles/876/1/Introduction-to-Pixel-Bender-and-Shader-for-Flash-Player-10/Page1.html

Tags: , ,

2 Comments

Open source AS3 frameworks to test run

With so many handy AS3 frameworks out there I often get excited about each new offering, but in the end I’m overwhelmed with the options and so rarely give any a test run.
 
Frameworks I use

Here’s a list of frameworks that I do rely on heavily and couldn’t live without (This is mostly for Flash website development).

PureMVC Brilliant MVC framework for AS3 (and a plethora of other platforms). This was my first foray into MVC and was hard going to get my head around, but now, I don’t look back!

swfAddress Integral for current Flash website development. Adds deep linking and browser history to your websites. Another good thing about swfAddress is that it forces you to use elements of good practice when developing your navigation code, it’s asymmetrical and requires a central navigation function.

Tweener One of the many Tween engines out there. I like Tweener because it’s simple to use and has shortcuts for really handy things (like colour effects and sound control). Most tween engines these days all do pretty much the same thing – either way they are vital tools for any actionscript animation.

And of course I have my own Tool and UI packages that I leverage on projects, being able to streamline and make more robust with each new job.
 
Frameworks to test run

But now to the point of this post. My new resolution is to tackle the mountain of frameworks out there, one at a time. I’ll do a quick “hello world” demo with each to get some hands on experience and see any potential for practical use. So, I’ll add to this list, but to start off with I’ll be looking at:

Flash Camoflage I don’t know too much about camoflage, but my general understanding is that it’s a Flash chrome and skinning framework

Tags: , , , , , ,

No Comments

Changing the behaviour of a class without recompiling.

This is a feature in AS3 that I hadn’t come accross before. If you ever load swf files into one another you might not know it, but you’ll be dealing with application domains. I’ve loaded in SWF’s before, but never had to pay any specific attention to the applicationDomain.

Basically they allow you to specify where the class definitions for an SWF are sourced from. By default if two SWF files use a class with the same name, then only the definition found in the parent SWF will be used. If you want the child SWF to use it’s own version of that class, then you need to give it it’s own application domain.

From the Adobe docs:

1
2
3
4
        request = new URLRequest("http://www.url.com/myflashfile.swf");
        var context:LoaderContext = new LoaderContext();
        context.applicationDomain= new applicationDomain()
        loader.load(request,context);

The current project I’m working on loads in a variety of SWFs that extend a common base class. It ended up that I needed to make a change to the base class, so at first I thought I was going to have to go and recompile all of the external swf files in order to incorporate the changes I’d made. But actually, this wasn’t the case due to the default behaviour of the applicationDomain. It turned out that as long as that base class was used in the parent swf, then all the external swfs that were loaded in would use the defintion found in it and not their own. Way to go! It meant that I could tweak and make changes to those external swfs, without ever open or recompile them. It’s turned out to be really useful, and painless!

Tags: , , , ,

No Comments