Latest snippets

MYSQL SOUNDEX

SELECT * FROM _users WHERE SOUNDEX(name) LIKE SOUNDEX('jon');

Not ActionScript, but the coolest thing I’ve seen in Mysql in awhile, the soundex function will convert a string into a soundex index… read more about it on wikipedia.

I did some tests and it matches things like:

what’s your name? & whats yer name

very cool… since this isn’t ActionScript, I will post another snippet right after this.

UPDATE: Actually started reading more about this stuff and dug up some algorithms… metaphone etc… fun stuff, maybe I’ll port some of it to actionscript…

Circles & cacheAsBitmap

[SWF(width=600,height=400,backgroundColor=0x000000,frameRate=30)]
var mcs:Vector.<MovieClip> = new Vector.<MovieClip>();
var num:int = 2000;
for (var i:int = 0; i<num; i++){
	var s:MovieClip = new MovieClip();
	s.graphics.lineStyle(0,0xFFFFFF);
	s.graphics.drawCircle(0,0, Math.random()*30 + 3);
	s.x = Math.random()*stage.stageWidth;
	s.y = Math.random()*stage.stageHeight;
       // comment out to kill your cpu
	s.cacheAsBitmap = true;
	addChild(s);
	s.vx  = Math.random() * 2 - 1;
	s.vy  = Math.random() * 2 - 1;
    mcs.push(s);
}
addEventListener(Event.ENTER_FRAME, onCenter);
function onCenter(evt:Event):void{
	for (var i:int = 0; i<num; i++){
		mcs[i].x += mcs[i].vx;
		mcs[i].y += mcs[i].vy;
	}
}

This was created in response to a question about the real speed gain of cacheAsBitmap. Just comment out the cacheAsBitmap line to see the difference.

Despite it’s extreme simplicity, this is actually a rather fun file to play with, change some of the graphics class method calls around and see what happens.

split() hacks & RegExp

var path:String = "section/home.swf";

var deepLinkValue:String = path.split("/")[1].split(".swf")[0];

trace(deepLinkValue);
/*outputs:
home
*/

As a primarily self taught programmer there was a time when I didn’t know what a regular expression was. There was also a time when ActionScript didn’t have them (you had to use a library). Sometimes when I’m in a rush I still do weird things like the above instead of regular expressions… pretty nasty I know.

Here are two different regular expressions that do the same thing:

var path = "section/home.swf"

trace(path.match(/w+(?=.)/))
/*outputs:
home
*/
 
trace(path.replace(/.+/|..+/g, ""))
/* also outputs:
home
*/

Actually, I’d be curious to see other regular expressions that only return one value (not an array) that achieve this same thing… feel free to post of a comment if you can think of one…

Is This swf Online?

private var _correctPath:String;

//.... somewhere a little later

 if (root.loaderInfo.url.split("http://").length == 1){
		_correctPath = "http://www.mywebsite.com/this/is/an/absolute/path/";
	}else{
		_correctPath = "";
	}

I like to do something like this when I’m working locally… it automatically tells my swf to use an absolute path for php files, xml files etc…. then, when I upload it, the LoaderInfo.url property contains an “http://” so it uses a relative path for all the external files. This is common especially if you don’t have php and mysql installed on your machine and need to test these using your server.

The Big init() #2

// see previous post for details, this code won't run on it's own
with(addChild(window)){
	x = 10, y = 10;
	with(addChild(c0)) x = 10, y = 10;
	with(addChild(c1)) x = 20, y = 10;
	with(addChild(box)){
		x = 50, y = 10;
		with(addChild(txt)) x = 5, y = 5;
	}
}

It’s entertaining to try and think of different DisplayObject nesting techniques. I have a few more of these rolling around in my head that I’ll try out soon…. The only good/notable thing about the above is that it shows that nested with statements actually work like you’d expect them to….

The Big init() (nesting DisplayObjects)

function nest(top:DisplayObjectContainer, structure:Array):void{
       var p:DisplayObjectContainer;
	   var key:String;
       for (var i:int = 0; i<structure.length; i++){
               if (structure[i] is DisplayObjectContainer){
                    p = structure[i];
					if (!p.parent){
                      top.addChild(p);
					}
                    i++;
                    if (structure[i] is Array){
                               var child:DisplayObject;
                               for (var j:int= 0; j<structure[i].length;  j++){
                                       var val:* = structure[i][j];
                                       if (val is DisplayObject){
                                               child = val;
                                               p.addChild(child);
                                       }else{
											   for (key in val){
												  child[key] = val[key];   
											   }
                                       }
                               }
                       }else{
                               trace("error, expecting Array");
							   break;
                       }
               }else{
                trace("error, expecting DisplayObjectContainer (Sprite or MovieClip)");
					   break;
               }
       }
}

// create some filler graphics
var window:Sprite = createWindow();
window.x = 10;
window.y = 10;

var c0:Sprite = createCircle();
var c1:Sprite = createCircle();
var c2:Sprite = createCircle();
var c3:Sprite = createCircle();
var c4:Sprite = createCircle(0xEFEFEF);

var box:Sprite = createBox(60, 50);


var txt:TextField = new TextField();
txt.text = "HI THERE";

// test out the function....
nest(this, [window, [ c0, {x:100, y:100, scaleX:.5, scaleY:.5},
                                    c1, {x:120, y:100, scaleX:.6, scaleY:.6},
                                    c2, {x:140, y:100, scaleX:.7, scaleY:.7},
                                    c3, {x:160, y:100, scaleX:.8, scaleY:.8},
								    box, {x:10, y:10} ],
	                    box, [ txt, c4,{x :30, y:30} ] ]); 


// just some quick functions to create filler graphics

function createBox(w:Number, h:Number):Sprite{
	var s:Sprite = new Sprite();
	with(s.graphics) beginFill(0x666666), drawRect(0,0, w, h);
	return s;
}
function createWindow():Sprite{
       var s:Sprite = new Sprite();
       with(s.graphics) beginFill(0xCCCCCC), drawRect(0,0,300,300);
       return s;
}
function createCircle(col:uint = 0xFF0000):Sprite{
       var s:Sprite = new Sprite();
       with(s.graphics) beginFill(col), drawCircle(0,0,10);
       return s;
}

The above uses a function called nest(). nest() is sort of like a superAddChild() function… it is meant to do the same thing as addChild, but with any number of parents and children.

I’m actually not very happy with this function, it was fun to write… but the 2D-Array/Object format is kind of odd looking (see line 53). So for at least the next day or two I’m going to try and think of the best format for a function that could do any number of addChild() calls with any number of children or parents. I realized that I also want to be able to set the properties of any of the children… so one solution might be an xml argument… something like:

<window>
  <c0 x="100" y="100" />
  <c1 x="200" y="100" />
  <c2 x="300" y="100" />
  <box x="400" y="100" alpha=".5">
     <c3 x="10" y="10" />
  </box>
</window>

That’s easy enough to do… it would be nice to think of something more minimalistic, but I think XML is much easier to read than JSON style Object syntax…

It’s actually interesting to try and think of minimalistic ways to represent tree structures… check out this failed attempt:

p(window);
__(c0, {x:100, y:100});
__(c1, {x:100, y:100});
__(c2, {x:100, y:100});

p(__(box, {x:100, y:100}));
__(txt, c4, {x:30, y:30});

After writing the above… a few hours later I thought of this:

propOrder("x", "y", "scaleX", "scaleY", "alpha");

bigInit(this, [window, [info, 10, 10,
                        about, 20, 10,
                        contact, 30, 10,
                        box, 40, 10, 2, 2, .5],
                  box, [txt0, 10, 10 * off(),
                        txt1, 10, 10 * off(),
                        txt2, 10, 10 * off(),
                        txt3, 10, 10 * off()],
                  border]);

I think that’s pretty close to what I was imagining in terms of simplicity.. the off() function would return an incremental offset… so call it once and it’s 0, call it again and it’s 1 etc… still not completely happy with this, but it’s getting there…

Any additional thoughts on this topic will be in tomorrows post I think.

“in” Operator

var obj:Object = {name: "Joe", hobby: "Guitar", age:"80"};

if ("name" in obj){
	trace(obj, " has a name property");
}

if ("x" in obj == false){
	trace(obj, " doesn't have an x property");
}


var mySprite:Sprite = new Sprite();

if ("currentFrame" in mySprite == false){
	trace(mySprite, "does not have a currentFrame property");
}

The “in” operator can be used to check if an object has a specific property. In the above example I test a standard Object instance and a Sprite instance for a few different properties.

I could see this operator being used when dealing with * (wildcard) datatypes and dynamic style code….

Crackable String Encoding

var encode:Object = new Object();
var decode:Object = new Object();
var a:Array = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".split("");

// change this for different encoded results
var offset:int = 10;

for (var i:int = 0; i<a.length; i++){
	var index:int = (a.length - i - offset) % a.length;
	encode[a[i]] = a[index];
	decode[a[index]] = a[i];
}

function encodeString(str:String):String{
	return map(str, encode);
}

function decodeString(str:String):String{
	return map(str, decode);
}

function map(str:String, smode:Object):String{
	var n:String = "";
	for (var i:int = 0; i<str.length; i++){
		var char:String = str.charAt(i);
		var en:String = smode[char];
		if (en){
		    n += en;
		}else{
			n += char;
		}
	}
	return n;
}

// test out the functions

var input:String = "This is a regular string";

trace(input);

var encoded:String = encodeString(input);

trace("encoded: ", encoded);

trace("decoded: ",decodeString(encoded));

/*
outputs:

This is a regular string
encoded:  gSRH1RH1Z1IVTFOZI1HGIRMT
decoded:  This is a regular string

*/

The above demos an intentionally simple string encoding technique.

This is a technique I use if I need to encode strings but don’t care if someone figures out what the string value actually is. For me, this is more common than needing hard/impossible to crack string encoding algorithms. A good example is an e-card… a url for an ecard could look like this:

www.birthdaycardthing.com/?name=joe&age=32

or it could look like this:

www.birthdaycardthing.com/?i=brx&x=5p

I wrapped this snippet up into a class and made a few minor tweaks. The class is called SimpleCipher it has two static methods and one static property…

import com.actionsnippet.utils.SimpleCipher;
// same as offset above, but can be set at any time
// new encode and decode Objects will be calculated
SimpleCipher.offset = 1;
var input:String = "SimpleCipher encoding and decoding";
			 
trace("input: ", input);
			 
var encoded:String = SimpleCipher.encode(input);
			 
trace("encoded: ", encoded);
trace("decoded: ", SimpleCipher.decode(encoded));
/*
outputs:
input:  SimpleCipher encoding and decoding
encoded:  RhlokdBhogdq0dmbnchmf0 mc0cdbnchmf
decoded:  SimpleCipher encoding and decoding
*/

Download SimpleCipher Class
(this class uses a static initializer… see yesterdays post)

Static Constructor / Initializer

package{
	
	public class Lookup{
		
		private static var _random:Array;
		// static initializer
		{
			trace("I am a static initializer for " + Lookup);
			init();
		}
		
		private static function init():void{
			 _random = new Array();
			 // generate some filler values
			 for (var i:int = 0; i<100; i++){
			 	_random.push(Math.random() * i);
			 }
		}
		
		public static function get random():Array{
			return _random.concat();
		}
	}
}

…and to test out the above class:

package {
	import flash.display.Sprite;

	public class Main extends Sprite{
		public function Main(){
           trace(Lookup.random[50]);
		}
	}
}
/*
outputs:
I am a static initializer for [class Lookup]
5.4258062043227255
*/

The above shows how to use static initializers. I’ve found this to be very handy… in this case we create an array of random values….

Tomorrow I’ll actually post a real class where I make use of this… the Lookup class in this case is really just filler code….