Quick QuickBox2D Tip – Runtime Skinning

Been playing around a quite a bit with QuickBox2D lately (check out my last post for one example), and have been loving it.

One of the coolest features I’ve found so far is being able to easily skin QuickObjects by just specifying a DisplayObject class as the skin property of the QuickObject’s params object. The one drawback to this feature is that the you can’t simply use a Sprite or MovieClip instance as the skin – you have to use the actual class. The bad part of this is that you’re limited at runtime to what you can use as a skin. Say for example you want to let your users draw their own boxes or you want to use a webcam shot as I did in my little game.

Well, though this may be obvious to most folks, the quick tip is this: The skin of a QuickObject can be referenced with the userData property. To create a custom skin at runtime, all you have to do is add a child to the current skin of the QuickObject instance with: someQO.userData.addChild(someDisplayObject);

One gotcha to watch out for is that by default, the skin is scaled to the dimensions of the QuickObject created. If you don’t want that behavior, you can specify scaleSkin as false in the params object.

Here’s a quickie example where 5 boxes are skinned with randomly generated Sprite instances:

The Main.as file:

package {
	
	import com.actionsnippet.qbox.QuickBox2D;
	import com.actionsnippet.qbox.QuickObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	[SWF(width='500', height='400', backgroundColor='#999999', frameRate='40')]
	public class Main extends MovieClip {
		
		public static const RATIO:int = 30;
		
		private var _sim:QuickBox2D;
		
		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);
			// entry point
			
			initWorld();
			
			var t:Timer = new Timer(1000, 5);
			t.addEventListener(TimerEvent.TIMER, addBox);
			t.start();
		}
		
		private function initWorld():void {
			_sim = new QuickBox2D(this);
			_sim.createStageWalls();
			_sim.mouseDrag();
			_sim.start();
		}
		
		private function addBox(event:TimerEvent):void {
			var boxGraphic:Sprite = randomBox();
			var w:Number = randRange(100, 20) / RATIO;
			var h:Number = randRange(100, 20) / RATIO;
			var box:QuickObject = _sim.addBox( { width:w, height:h, skin:Skin } );
			box.userData.addChild(boxGraphic);
		}
		
		private function randomBox():Sprite {
			var c:uint = Math.random() * 0xFFFFFF;
			var s:Sprite = new Sprite();
			s.graphics.beginFill(c);
			s.graphics.drawRect( -50, -50, 100, 100);
			s.graphics.endFill();
			return s;
		}
		
		private function randRange(max:Number, min:Number = 0, decimals:int = 0):Number {
			if (min > max) return NaN;
			var rand:Number = Math.random() * (max-min + Math.pow(10, -decimals)) + min;
			return int(rand * Math.pow(10, decimals)) / Math.pow(10, decimals);
		}
	}
}

And the very simple Skin.as:

package  {

	import flash.display.Sprite;
	
	public class Skin extends Sprite{
		
		public function Skin() {
			graphics.beginFill(0x000000);
			graphics.drawRect( -50, -50, 100, 100);
			graphics.endFill();
		}
	}
}
Date: