DAN ZEN EXPO - CODE EXHIBIT - PENGUIN


package samples {

   	import flash.display.MovieClip;
    	import flash.display.Sprite;
    	import flash.events.*;
	import flash.filters.*;
	
	// see the Penguin.as file located at the path below for instructions on installing classes
		
	import com.danzen.interfaces.Penguin;
	
	// PENGUIN INTRODUCTION  
	// Penguin is a simple class that retreives XML specifying tilt and translation
	// an event is set to tell us when these have changed
	// and properties for roll, pitch, yaw and translation x, y, and z are provided
	// http://penguinsflash.wordpress.com - by inventor Dan Zen - http://www.danzen.com
	// if you are using Penguin for commercial purposes, you are welcome to donate to Dan Zen
	// donations can be made to agency@danzen.com at http://www.paypal.com
	
	// PENGUIN OVERVIEW  
	// Various mobile hardware / software might provide tilt and translation data
	// this could be an accelerometer or a camera with motion detection
	// to get your Flash project ready for such data Penguin was created
	// Penguin provides a Tilt Emulator that you can operate instead of your mobile device
	// there are three setups exemplified: samples, samples_pop and samples_cuddle as follows:
	
	// 1. samples folder
	//    In the sample folder is the Penguin Tilt Emulator AIR file
	//    double click this to install and run the emulator
	//    you will need Adobe AIR which runs Flash files as desktop applications
	//    AIR takes less than a minute to install and is quite automatic
	//    the emulator lets you tilt a "device" in 3D in two modes and two orientations
	//	  tilt and translation data from the emulator is written to your Application Directory
	//    the emulator tells you at the bottom the URL of this XML file (tilt.xml)
	//    this set up is more real than the two set ups detailed next
	//    if you can get real data to be written to the XML then your Flash is ready to go!
	
	// 2. samples_pop folder
	//    use this or the next setup to show someone on the Web how this might work
	//    when the viewer runs the sample html and swf, a window with an emulator swf pops up
	
	// 3. sampes_cuddle folder
	//    again, this works for the Web as the sample and the emulator swf are on the same page
	//    these last two setups sort of take away from the purpose of Penguin
	//    Penguin is to let you visualize and test tilt and translation applications
	//    ideally, your application will connect to real tilt and translation data 
	
	// USING PENGUIN   
	// please make sure that the provided com folder is in a folder in your class path
	// **** do not put the com folder in your class path
	// but rather, for instance, make a classes folder and add that to your class path
	// then put the com folder in the classes folder
	// and make sure that the danzen/interfaces/ folder with Penguin.as is in com
	// see the Penguin.as file or the readme.txt for details
	
	// CONSTRUCTOR  
	// Penguin(xmlPath:String):void
	//	constructor to connect to an XML file that has tilt and/or translation data
	//	PARAMETERS:
	//		xmlPath:String
	//			the file path to the tilt XML - for instance left by the emulator
	//          ideally, this would be created by a Java program on your mobile device
	//          could be a URL but this is not ideal due to latency
	//			most likely it will be on the same computer / device so connection is fast
	//			there is no need for sockets which are for connection between servers
				
	// EVENTS 
	// PenguinPop.MOTION_START
	//		dispatched when motion starts (this is at any motion start as the applicatin runs)
	// PenguinPop.MOTION_START
	//		dispatched when there has been no motion in motionInterval seconds (see getter setter methods)
	// Event.CHANGE
	//		dispatched when the tilt file is read - every period seconds - so not necessarily a change

	// METHODS 
	// transposeValue(a:String, b:String):void
	// 		if the data coming in is not how you want to work with it
	// 		for instance, you want pitch to be -pitch or roll to be yaw...
	//		a is the original data which will be changed to values from b
	// 		properties you change are roll pitch yaw forward right down
	//		you can also specify negatives like transposeValue("pitch", "-yaw");
	// 		see the method for more info
	// dispose():void
	// 		stops tracking beats and removes listeners, etc.

	// PROPERTIES  
	// view:String - sets or gets emulator view - default "top" other values: "front"
	// orientation:String - sets or gets emulator orientation default "vertical" other values: "horizontal"
	// roll:Number - (read only) clockwise rotation around the forward direction
	// pitch:Number - (read only) clockwise rotation around the right direction
	// yaw:Number - (read only) clockwise rotation around the down direction
	// forward:Number - (read only) direction of travel or user's view
	// right:Number - (read only) direction perpendicular to the forward direction and laterally to the right
	// down:Number - (read only) direction perpendicular to the forward and right and in the down direction
	// tiltUnits:String - (read only) default for the Penguin emulator is "degrees"
	// translationUnits:String - (read only) default for the Penguin emulator is "screens"
	// xmlData:XML - (read only) - the full XML from the emulator
	// transposeList:Array - sets or gets a list of transpositions (alternative to transposeValue method)
	// motionInterval:Number - sets or gets seconds of no motion before the STOP_MOTION event is triggered

	// CONSTANTS  
	// MOTION_START:String - static constant (Penguin.MOTION_START) for motion start event
	// MOTION_STOP:String - static constant (Penguin.MOTION_STOP) for motion stop event

    public class TiltBall extends MovieClip {
		
		private var myPenguin:Penguin;
		
		private var myBall:Sprite = new Sprite();
		private var moveX:Number = 0;
		private var moveY:Number = 0;
		private var sW:Number;
		private var sH:Number;
		private var speed:Number = 1;
		
		public function TiltBall() {
			
			// create a Penguin object to track tilt and translation data
			// this data comes from an XML file of tiltML format
			// pass the file path to this data file into the Penguin object as a parameter
			// The Penguin Tilt Emulator tells you the path at the bottom of the screen
			// **** so you must get that URL and paste it as the value for myFile below
			// if you are getting data created from another program put that path here			
			
			var myFile:String = "file:///C:/somepath/tilt.xml";
			myPenguin = new Penguin(myFile);
			myPenguin.addEventListener(Event.CHANGE, doTilt);

			// create the ball and an animate ENTER_FRAME Event
			myBall.graphics.beginFill(0xFFFFFF);
			myBall.graphics.drawCircle(0,0,50);
			myBall.x = 300;
			myBall.y = 200;
			myBall.filters = [new GlowFilter(0x000000, 1, 30, 30, .8, 3, true)];
			addChild(myBall);
			sW = stage.stageWidth;
			sH = stage.stageHeight;
			
			addEventListener(Event.ENTER_FRAME, doAnimation);		
			
		}		
		
		
		private function doTilt(e:Event) {		
		
			// retrieve the roll and pitch properties
			// adjust the move variables which will be used in the animate function
			
			moveX = e.target.roll;
			moveY = e.target.pitch;			
		}
		
		private function doAnimation(e:Event) {	
		
			// use the move variables from the tilt data 
			// multiply it times a speed factor 
			// apply limits to the movement
			// this is very basic - you can use physics (see cove's APE classes)
			// a sampe swf file is provided as an example of what physics would be like			
			
			myBall.x += moveX * speed;
			myBall.y += moveY * speed;
			
			if (myBall.x > sW-myBall.width/2) {myBall.x = sW-myBall.width/2;}
			if (myBall.y > sH-myBall.width/2) {myBall.y = sH-myBall.width/2;}
			if (myBall.x < 0+myBall.width/2) {myBall.x = myBall.width/2;}
			if (myBall.y < 0+myBall.width/2) {myBall.y = myBall.width/2;}
			
		}
		
    }
} 

package com.danzen.interfaces.penguin {

	// PENGUIN / PENGUINPOP / PENGUINCUDDLE INTRODUCTION  
	// Penguin is a system where you can emulate mobile device rotation and translation in Flash
	// this lets you create "tilt" applications independent from the technology
	// for instance, rolling a ball around in a maze or steering a car on a mobile device
	// the emulator leaves the data, this class reads it and passes it to your Flash application
	// so if you can get something to leave the data for you, your application is ready to roll!

	// http://penguinsflash.wordpress.com - by inventor Dan Zen - http://www.danzen.com
	// if you are using Penguin for commercial purposes, you are welcome to donate to Dan Zen
	// donations can be made to agency@danzen.com at http://www.paypal.com

	// INSTALLING CLASSES  
	// suggested installation:
	// create a "classes" folder on your hard drive - for example c:\classes
	// add the classes folder to your Flash class path:
	// Flash menu choose Edit > Preferences > ActionScript - ActionScript 3 Settings 
	// then use the + sign for the source path box to add the path to your classes folder
	// put the provided com/danzen/ directory with its folders and files in the classes folder
	// the readme has more information if you need it

	// USING PENGUIN  
	// please make sure that the following files are in a folder in your class path:
	// 		com/danzen/interfaces/penguin/Penguin.as
	// 		com/danzen/interfaces/penguin/PenguinPop.as
	// 		com/danzen/interfaces/penguin/PenguinCuddle.as
	// 		com/danzen/utilities/Falcon.as
	// the three penguin classes are alternatives and act independently
	// the Penguin.as file uses Falcon.as but the other two do not

	// Penguin
	// Examples using Penguin are in the samples folder
	// in this version, you double click and install the penguinTiltEmulator.air file
	// you will need AIR from http://adobe.com it is free and fast to install
	// the emulator writes XML on to your computer to simulate a device writing data
	// the data is in the form of TiltML or Tilt Markup Language
	// http://tiltml.wordpress.com
	// Flash then reads in the XML and you power your motion from it
	// see the diagrams that come with Penguin to better understand the data
	// this is roll pitch yaw forward right down data

	// any samples that make use of physics engines are presented as swf files only
	// they use the APE physics engine available at http://www.cove.org/ape/

	// PenguinPop
	// Examples using Penguin are in the samples_pop folder
	// in this version, the tilt emulator is popped up in a new window
	// communication with your Flash application is through the LocalConnection class
	// it can be used to show people in the Web your prototype
	// but it does not read in an XML file so will not be optimal for a real application

	// PenguinCuddle
	// Examples using Penguin are in the samples_cuddle folder
	// here, the tilt emulator is loaded into a holder swf file along with your application
	// communication with your Flash application is through a "global" variable
	// like PenguinPop it can be used to show people in the Web your prototype
	// but it does not read in an XML file so will not be optimal for a real application
	// there is a list of methods, events and properties below for reference
	// see the example files that come with Penguin to see how to use Penguin

	import flash.display.Sprite;
	import flash.events.*;
	import flash.utils.Timer;

	import com.danzen.utilities.Falcon;

	public class Penguin extends Sprite {

		// CONSTRUCTOR  
		// Penguin(theFilePath:String):void
		//  	constructor to start read the XML left by the AIR PenguinTiltEmulator
		//  	your application can start before or after you run the Emulator
		//  	but there will be no data unless the Emulator is running		
		// 		PARAMETERS:
		// 		theFilePath:String
		// 			the file path to the XML file the emulator writes to
		// 			the AIR Penguin Emulator gives you the path at the bottom in a field
		// 			it is usually in some application data directory
		//          if you are on a mobile device and Java for instance is writing the XML
		//          then you would use the path to that XML file
		//          see http://tiltml.wordpress.com for the format and discussion

		// EVENTS 
		// PenguinPop.MOTION_START
		//		dispatched when motion starts (this is at any motion start as the applicatin runs)
		// PenguinPop.MOTION_START
		//		dispatched when there has been no motion in motionInterval seconds (see getter setter methods)
		// Event.CHANGE
		//		dispatched when the tilt file is read - every period seconds - so not necessarily a change

		// METHODS 
		// transposeValue(a:String, b:String):void
		// 		if the data coming in is not how you want to work with it
		// 		for instance, you want pitch to be -pitch or roll to be yaw...
		//		a is the original data which will be changed to values from b
		// 		properties you change are roll pitch yaw forward right down
		//		you can also specify negatives like transposeValue("pitch", "-yaw");
		// 		see the method for more info
		// dispose():void
		// 		stops tracking beats and removes listeners, etc.

		// PROPERTIES  
		// view:String - sets or gets emulator view - default "top" other values: "front"
		// orientation:String - sets or gets emulator orientation default "vertical" other values: "horizontal"
		// roll:Number - (read only) clockwise rotation around the forward direction
		// pitch:Number - (read only) clockwise rotation around the right direction
		// yaw:Number - (read only) clockwise rotation around the down direction
		// forward:Number - (read only) direction of travel or user's view
		// right:Number - (read only) direction perpendicular to the forward direction and laterally to the right
		// down:Number - (read only) direction perpendicular to the forward and right and in the down direction
		// tiltUnits:String - (read only) default for the Penguin emulator is "degrees"
		// translationUnits:String - (read only) default for the Penguin emulator is "screens"
		// xmlData:XML - (read only) - the full XML from the emulator
		// transposeList:Array - sets or gets a list of transpositions (alternative to transposeValue method)
		// motionInterval:Number - sets or gets seconds of no motion before the STOP_MOTION event is triggered

		// CONSTANTS  
		// MOTION_START:String - static constant (Penguin.MOTION_START) for motion start event
		// MOTION_STOP:String - static constant (Penguin.MOTION_STOP) for motion stop event

		public static const MOTION_START:String = "motion start";
		public static const MOTION_STOP:String = "motion stop";

		public var view:String = "top";
		public var orientation:String = "vertical";
		public var roll:Number = 0;
		public var pitch:Number = 0;
		public var yaw:Number = 0;
		public var forward:Number = 0;
		public var right:Number = 0;
		public var down:Number = 0;
		public var tiltUnits:String = "degrees";
		public var translationUnits:String = "screens";
		public var xmlData:XML;
		public var transposeList:Array;

		private var myTimer:Timer;
		private var myFalcon:Falcon;
		private var filePath:String;
		private var dataNames:Array = ["pitch","roll","yaw","forward","right","down"];

		// variables for stop and start detection
		private var motionState:String = Penguin.MOTION_START;
		private var motionLast:Array = [0,0,0,0,0,0];
		private var motionCount:Number = 0;
		private var period:Number = 200;// ms between tilt data readings
		private var myMotionInterval:Number = 1;// seconds of no motion until stop is determined
		private var loopModulus:Number;

		public function Penguin(theFilePath:String="tiltml.xml") {

			filePath = theFilePath;

			trace("hi from Penguin");
			trace("analyzing: " + filePath);

			transposeList = dataNames.concat();

			myTimer = new Timer(period);
			myTimer.start();
			myTimer.addEventListener(TimerEvent.TIMER,getData);

		}

		private function getData(e:TimerEvent) {
			if (myFalcon) {
				myFalcon.removeEventListener(Event.COMPLETE,doTilt);
			}
			myFalcon = new Falcon(filePath,Falcon.XML_DATA);
			myFalcon.addEventListener(Event.COMPLETE,doTilt);
		}

		private function doTilt(e:Event) {
			if (e.target.error) {
				return;
			}
			xmlData = e.target.data;

			view = xmlData.view;
			orientation = xmlData.orientation;// sorry for the keyword ;-(
			pitch = xmlData.tilt. @ pitch;
			roll = xmlData.tilt. @ roll;
			yaw = xmlData.tilt. @ yaw;
			forward = xmlData.translation. @ forward;
			right = xmlData.translation. @ right;
			down = xmlData.translation. @ down;
			tiltUnits = xmlData.tilt. @ units;
			translationUnits = xmlData.translation. @ units;

			// check for transposition
			if (dataNames.toString() != transposeList.toString()) {
				var len:uint = dataNames.length;
				var orig:Array = [];
				// store the originals
				for (var i:uint = 0; i < len; i++) {
					orig.push(this[dataNames[i]]);
				}
				var val:String;
				var val2:String;
				var sign:Number = 1;
				for (i = 0; i < len; i++) {
					if (dataNames[i] == transposeList[i]) {
						continue;
					}
					val = transposeList[i];
					val2 = val.replace(/-\s*/g,"");
					if (val != val2) {
						sign = -1;
					}
					this[dataNames[i]] = sign * orig[dataNames.indexOf(val2)];
				}
			}

			// check for motion start and stop
			if (motionState == PenguinPop.MOTION_STOP) {
				if (! compareArray([roll,pitch,yaw,forward,right,down],motionLast)) {
					motionState = PenguinPop.MOTION_START;
					motionCount = 0;
					dispatchEvent(new Event(PenguinPop.MOTION_START));
				}
				motionLast = [roll,pitch,yaw,forward,right,down];
			} else {
				motionCount++;
				if (motionCount % loopModulus == 0) {
					if (compareArray([roll,pitch,yaw,forward,right,down],motionLast)) {
						motionState = PenguinPop.MOTION_STOP;
						dispatchEvent(new Event(PenguinPop.MOTION_STOP));
					}
					motionLast = [roll,pitch,yaw,forward,right,down];
				}
			}
			function compareArray(a1,a2) {
				var checkArray:Boolean = true;
				var len:Number = a1.length;
				for (var i:uint = 0; i < len; i++) {
					if (a1[i] != a2[i]) {
						checkArray = false;
						break;
					}
				}
				return checkArray;
			}

			dispatchEvent(new Event(Event.CHANGE));
		}

		public function transposeValue(a:String,b:String) {
			// a is the original data which will be changed to b
			// for instance to change pitch to be the value from yaw
			// transpose("pitch", "yaw")
			// this does not swap the values as you will rarely want to do that
			// original data names are pitch roll yaw forward right down
			// you can also change to a negative like so:
			// transpose("pitch","-pitch"); // or transpose("down","-forward");
			// now the transposeList stores the b value
			// that corresponds to the value in the dataNames
			// the transposeList is used to transpose the data in the doTilt function
			transposeList[dataNames.indexOf(a)] = b;
		}

		public function set motionInterval(s:Number):void {
			// how many seconds does motion have to be the same for MOTION_STOP to trigger
			myMotionInterval = s;
			loopModulus = Math.max(1,Math.floor(myMotionInterval * 1000 / period));
		}

		public function get motionInterval():Number {
			return myMotionInterval;
		}

		public function dispose() {
			myTimer.removeEventListener(TimerEvent.TIMER,getData);
			myTimer.stop();
			myTimer = null;
		}

	}
}


package com.danzen.interfaces.penguin {

	// PENGUIN / PENGUINPOP / PENGUINCUDDLE INTRODUCTION  
	// Penguin is a system where you can emulate mobile device rotation and translation in Flash
	// this lets you create "tilt" applications independent from the technology
	// for instance, rolling a ball around in a maze or steering a car on a mobile device
	// the emulator leaves the data, this class reads it and passes it to your Flash application
	// so if you can get something to leave the data for you, your application is ready to roll!
	
	// http://penguinsflash.wordpress.com - by inventor Dan Zen - http://www.danzen.com
	// if you are using Penguin for commercial purposes, you are welcome to donate to Dan Zen
	// donations can be made to agency@danzen.com at http://www.paypal.com
	
	// INSTALLING CLASSES  
	// suggested installation:
	// create a "classes" folder on your hard drive - for example c:\classes
	// add the classes folder to your Flash class path:
	// Flash menu choose Edit > Preferences > ActionScript - ActionScript 3 Settings 
	// then use the + sign for the source path box to add the path to your classes folder	
	// put the provided com/danzen/ directory with its folders and files in the classes folder
	// the readme has more information if you need it

	// USING PENGUIN  
	// please make sure that the following files are in a folder in your class path:	
	// 		com/danzen/interfaces/penguin/Penguin.as
	// 		com/danzen/interfaces/penguin/PenguinPop.as
	// 		com/danzen/interfaces/penguin/PenguinCuddle.as
	// 		com/danzen/utilities/Falcon.as
	// the three penguin classes are alternatives and act independently	
	// the Penguin.as file uses Falcon.as but the other two do not
	
	// Penguin
	// Examples using Penguin are in the samples folder
	// in this version, you double click and install the penguinTiltEmulator.air file
	// you will need AIR from http://adobe.com it is free and fast to install
	// the emulator writes XML on to your computer to simulate a device writing data
	// the data is in the form of TiltML or Tilt Markup Language
	// http://tiltml.wordpress.com
	// Flash then reads in the XML and you power your motion from it
	// see the diagrams that come with Penguin to better understand the data
	// this is roll pitch yaw forward right down data
	
	// any samples that make use of physics engines are presented as swf files only
	// they use the APE physics engine available at http://www.cove.org/ape/
	
	// PenguinPop
	// Examples using Penguin are in the samples_pop folder
	// in this version, the tilt emulator is popped up in a new window
	// communication with your Flash application is through the LocalConnection class
	// it can be used to show people in the Web your prototype
	// but it does not read in an XML file so will not be optimal for a real application
	
	// PenguinCuddle
	// Examples using Penguin are in the samples_cuddle folder
	// here, the tilt emulator is loaded into a holder swf file along with your application
	// communication with your Flash application is through a "global" variable
	// like PenguinPop it can be used to show people in the Web your prototype
	// but it does not read in an XML file so will not be optimal for a real application	
		
	// there is a list of methods, events and properties below for reference	
	// see the example files that come with Penguin to see how to use Penguin		


	import flash.display.Sprite;
	import flash.display.MovieClip;
	import flash.events.*;
	import flash.net.LocalConnection;
	import flash.utils.Timer;
	
	public class PenguinCuddle extends Sprite {
		
		// CONSTRUCTOR
		// PenguinCuddle(theView:String="top", theOrientation:String="vertical", theFreedom:String="two"):void
		//		constructor to set the Tilt emulator settings
		//		this is different than the Penguin constructor
		//		Penguin is a for you testing your application so you control the emulator
		//		Here, you are displaying your prototype on the Web
		//		so you probably want to start the emulator in the right view, orientation and freedom
		//		PARAMETERS:
		//		theView:String
		//			- default "top" other values: "front"
		//			- top view looks down on the device with the screen parallel to the ground
		//			- front view is holding the device up in front of you with screen perpendicular to the ground
		//		theOrientation:String
		//			- default "vertical" other values: "horizontal"
		//			- just the way the screen is oriented
		//			- depending on your device, this may or may not be important to your readings
		//			- if there is an issue you can always transpose your data
		//		theFreedom:String 
		//			- default "two"	other values: "one"
		//			- are you in two plane tilt mode or one plane rotation mode
		//			- this is just an tilt emulator interface issue so does not effect data
		//			- it was just easier to navigate if we separate out the perpendicular axis
				
		// EVENTS
		// Event.CONNECT
		//		the emulator is ready for setting view, orientation and freedom
		// PenguinPop.MOTION_START
		//		dispatched when motion starts (this is at any motion start as the applicatin runs)
		// PenguinPop.MOTION_START
		//		dispatched when there has been no motion in motionInterval seconds (see getter setter methods)
		// Event.CHANGE
		//		dispatched when the emulator sends data 
		
		// METHODS
		// transposeValue(a:String, b:String):void
		// 		if the data coming in is not how you want to work with it
		// 		for instance, you want pitch to be -pitch or roll to be yaw...
		//		a is the original data which will be changed to values from b
		// 		properties you change are roll pitch yaw forward right down
		// 		you can also specify negatives like transposeValue("pitch", "-yaw");
		// 		see the method for more info
		// setView(v:String):void 
		//		sets the emulator view - v can be either "top" or "front"
		// setOrientation(o:String):void
		//		sets the orientation on the emulator - o can be "horizontal" or "vertical"
		// setFreedom(f:String):void 
		//		sets the freedom on the emulator - f can be "one" or "two"
		// dispose():void
		// 		stops tracking beats and removes listeners, etc.
		
		// PROPERTIES 	
		// view:String - sets or gets emulator view - default "top" other values: "front"
		// orientation:String - sets or gets emulator orientation default "vertical" other values: "horizontal"
		// roll:Number - (read only) clockwise rotation around the forward direction
		// pitch:Number - (read only) clockwise rotation around the right direction
		// yaw:Number - (read only) clockwise rotation around the down direction
		// forward:Number - (read only) direction of travel or user's view
		// right:Number - (read only) direction perpendicular to the forward direction and laterally to the right
		// down:Number - (read only) direction perpendicular to the forward and right and in the down direction
		// tiltUnits:String - (read only) default for the Penguin emulator is "degrees"
		// translationUnits:String - (read only) default for the Penguin emulator is "screens"
		// xmlData:XML - (read only) - the full XML from the emulator
		// transposeList:Array - sets or gets a list of transpositions (alternative to transposeValue method)				
		// motionInterval:Number - sets or gets seconds of no motion before the STOP_MOTION event is triggered
	
		// CONSTANTS
		// MOTION_START:String - static constant (Penguin.MOTION_START) for motion start event
		// MOTION_STOP:String - static constant (Penguin.MOTION_STOP) for motion stop event	
				
		public static const MOTION_START:String = "motion start";
		public static const MOTION_STOP:String = "motion stop";		
		
		public var view:String = "top";
		public var orientation:String = "vertical";
		public var roll:Number = 0;
		public var pitch:Number = 0;
		public var yaw:Number = 0;
		public var forward:Number = 0;
		public var right:Number = 0;
		public var down:Number = 0;
		public var tiltUnits:String = "degrees";
		public var translationUnits:String = "screens";
		public var xmlData:XML;
		public var transposeList:Array;	
		
		private var myConnectionSend:LocalConnection = new LocalConnection();		
		private var myTimer:Timer;
		private var dataNames:Array = ["pitch", "roll", "yaw", "forward", "right", "down"];
		private var myView:String;
		private var myOrientation:String;
		private var myFreedom:String;
		
		private var motionState:String = PenguinCuddle.MOTION_START;
		private var motionLast:Array = [0,0,0,0,0,0];
		private var motionCount:Number = 0;
		private var period:Number = 200; // ms between tilt data readings
		private var myMotionInterval:Number = 1;  // seconds of no motion until stop is determined
		private var loopModulus:Number; 		

        public function PenguinCuddle(
					theView:String = "top",
					theOrientation:String = "vertical",
					theFreedom:String = "two"					
					) {	
		
			trace ("hi from PenguinCuddle");
			
			addEventListener(Event.ENTER_FRAME, getTiltData);
			
			myView = theView;
			myOrientation = theOrientation;
			myFreedom = theFreedom;	
						
			transposeList = dataNames.concat();
			
			myTimer = new Timer(200);
			myTimer.start();
			myTimer.addEventListener(TimerEvent.TIMER, checkEmulator);			
			
			myConnectionSend.addEventListener(StatusEvent.STATUS, onStatus);			
		}
		
		public function checkEmulator(e:TimerEvent) {
			if (!MovieClip.prototype.myXML) {return;}
			myTimer.stop();
			myTimer.removeEventListener(TimerEvent.TIMER, checkEmulator);
			setView(myView);
			setOrientation(myOrientation);
			setFreedom(myFreedom);
			dispatchEvent(new Event(Event.CONNECT));
		}		
		
		private function onStatus(event:StatusEvent):void {
			switch (event.level) {
				case "status" :
					//trace("LocalConnection.send() succeeded");
					break;
				case "error" :
					//trace("LocalConnection.send() failed");
					break;
			}
		}			
		
		public function getTiltData(e:Event) {

			var xmlData:XML;
			if (!MovieClip.prototype.myXML) {return;}
				
			xmlData = XML(MovieClip.prototype.myXML);
			
			view = xmlData.view;
			orientation = xmlData.orientation;			
			roll = xmlData.tilt.@roll;
			pitch = xmlData.tilt.@pitch;
			yaw = xmlData.tilt.@yaw;
			forward = xmlData.translation.@forward;
			right = xmlData.translation.@right;
			down = xmlData.translation.@down;
			tiltUnits = xmlData.tilt.@units;
			translationUnits = xmlData.translation.@units;

			// check for transposition
			if (dataNames.toString() != transposeList.toString()) {
				var len:uint = dataNames.length;
				var orig:Array = [];
				// store the originals
				for (var i:uint = 0; i < len; i++) {
					orig.push(this[dataNames[i]]);
				}
				var val:String;
				var val2:String;
				var sign:Number = 1;
				for (i = 0; i < len; i++) {
					if (dataNames[i] == transposeList[i]) {continue;}
					val = transposeList[i];
					val2 = val.replace(/-\s*/g, "");
					if (val != val2) {
						sign = -1;
					}
					this[dataNames[i]] = sign * orig[dataNames.indexOf(val2)];
				}
			}
			
			// check for motion start and stop
			if (motionState == PenguinPop.MOTION_STOP) {
				if (!compareArray([roll,pitch,yaw,forward,right,down], motionLast)) {
					motionState = PenguinPop.MOTION_START;
					motionCount = 0;					
					dispatchEvent(new Event(PenguinPop.MOTION_START));
				}
				motionLast = [roll,pitch,yaw,forward,right,down];
			} else {
				motionCount++;				
				if (motionCount % loopModulus == 0) {
					if (compareArray([roll,pitch,yaw,forward,right,down], motionLast)) {						
						motionState = PenguinPop.MOTION_STOP;
						dispatchEvent(new Event(PenguinPop.MOTION_STOP));
					}					
					motionLast = [roll,pitch,yaw,forward,right,down];
				}
			}				
			function compareArray(a1,a2) {
				var checkArray:Boolean = true;
				var len:Number = a1.length;
				for (var i:uint=0; i<len; i++) {
					if (a1[i] != a2[i]) {checkArray = false; break;}
				}				
				return checkArray;
			}
											
			dispatchEvent(new Event(Event.CHANGE));
		}
		public function setView(v:String):void {
			myConnectionSend.send("Emulator", "setView", myView);
		}
		public function setOrientation(o:String):void {
			myConnectionSend.send("Emulator", "setOrientation", myOrientation);
		}
		public function setFreedom(f:String):void {
			myConnectionSend.send("Emulator", "setFreedom", myFreedom);
		}		
		
		public function transposeValue(a:String, b:String) {
			// a is the original data which will be changed to b
			// for instance to change pitch to be the value from yaw
			// transpose("pitch", "yaw")
			// this does not swap the values as you will rarely want to do that
			// original data names are pitch roll yaw forward right down
			// you can also change to a negative like so:
			// transpose("pitch","-pitch"); // or transpose("down","-forward");
			// now the transposeList stores the b value
			// that corresponds to the value in the dataNames
			// the transposeList is used to transpose the data in the doTilt function
			transposeList[dataNames.indexOf(a)] = b;
		}		
		
		public function set motionInterval(s:Number):void { // how many seconds does motion have to be the same for MOTION_STOP
			myMotionInterval = s;
			loopModulus = Math.max(1, Math.floor(myMotionInterval * 1000 / period));			
		}
		
		public function get motionInterval():Number {
			return myMotionInterval;
		}		
		
		public function dispose() {
			removeEventListener(Event.ENTER_FRAME, getTiltData);
		}		
		
    }
} 


package com.danzen.interfaces.penguin {

	// PENGUIN / PENGUINPOP / PENGUINCUDDLE INTRODUCTION  
	// Penguin is a system where you can emulate mobile device rotation and translation in Flash
	// this lets you create "tilt" applications independent from the technology
	// for instance, rolling a ball around in a maze or steering a car on a mobile device
	// the emulator leaves the data, this class reads it and passes it to your Flash application
	// so if you can get something to leave the data for you, your application is ready to roll!
	
	// http://penguinsflash.wordpress.com - by inventor Dan Zen - http://www.danzen.com
	// if you are using Penguin for commercial purposes, you are welcome to donate to Dan Zen
	// donations can be made to agency@danzen.com at http://www.paypal.com
	
	// INSTALLING CLASSES  
	// suggested installation:
	// create a "classes" folder on your hard drive - for example c:\classes
	// add the classes folder to your Flash class path:
	// Flash menu choose Edit > Preferences > ActionScript - ActionScript 3 Settings 
	// then use the + sign for the source path box to add the path to your classes folder	
	// put the provided com/danzen/ directory with its folders and files in the classes folder
	// the readme has more information if you need it

	// USING PENGUIN  
	// please make sure that the following files are in a folder in your class path:	
	// 		com/danzen/interfaces/penguin/Penguin.as
	// 		com/danzen/interfaces/penguin/PenguinPop.as
	// 		com/danzen/interfaces/penguin/PenguinCuddle.as
	// 		com/danzen/utilities/Falcon.as
	// the three penguin classes are alternatives and act independently	
	// the Penguin.as file uses Falcon.as but the other two do not
	
	// Penguin
	// Examples using Penguin are in the samples folder
	// in this version, you double click and install the penguinTiltEmulator.air file
	// you will need AIR from http://adobe.com it is free and fast to install
	// the emulator writes XML on to your computer to simulate a device writing data
	// the data is in the form of TiltML or Tilt Markup Language
	// http://tiltml.wordpress.com
	// Flash then reads in the XML and you power your motion from it
	// see the diagrams that come with Penguin to better understand the data
	// this is roll pitch yaw forward right down data
	
	// any samples that make use of physics engines are presented as swf files only
	// they use the APE physics engine available at http://www.cove.org/ape/
	
	// PenguinPop
	// Examples using Penguin are in the samples_pop folder
	// in this version, the tilt emulator is popped up in a new window
	// communication with your Flash application is through the LocalConnection class
	// it can be used to show people in the Web your prototype
	// but it does not read in an XML file so will not be optimal for a real application
	
	// PenguinCuddle
	// Examples using Penguin are in the samples_cuddle folder
	// here, the tilt emulator is loaded into a holder swf file along with your application
	// communication with your Flash application is through a "global" variable
	// like PenguinPop it can be used to show people in the Web your prototype
	// but it does not read in an XML file so will not be optimal for a real application	
		
	// there is a list of methods, events and properties below for reference	
	// see the example files that come with Penguin to see how to use Penguin		

	import flash.display.Sprite;
    import flash.events.*;	
	import flash.net.LocalConnection; 	
	
    public class PenguinPop extends Sprite {
		
		// CONSTRUCTOR
		// PenguinPop(theView:String="top", theOrientation:String="vertical", theFreedom:String="two"):void
		//		constructor to set the Tilt emulator settings in the pop-up
		//		this is different than the Penguin constructor
		//		Penguin is a for you testing your application so you control the emulator
		//		Here, you are displaying your prototype on the Web
		//		so you probably want to start the emulator in the right view, orientation and freedom
		//		PARAMETERS:
		//		theView:String
		//			- default "top" other values: "front"
		//			- top view looks down on the device with the screen parallel to the ground
		//			- front view is holding the device up in front of you with screen perpendicular to the ground
		//		theOrientation:String
		//			- default "vertical" other values: "horizontal"
		//			- just the way the screen is oriented
		//			- depending on your device, this may or may not be important to your readings
		//			- if there is an issue you can always transpose your data
		//		theFreedom:String 
		//			- default "two"	other values: "one"
		//			- are you in two plane tilt mode or one plane rotation mode
		//			- this is just an tilt emulator interface issue so does not effect data
		//			- it was just easier to navigate if we separate out the perpendicular axis
				
		// EVENTS
		// Event.CONNECT
		//		the emulator in the pop up window is ready for setting view, orientation and freedom
		// PenguinPop.MOTION_START
		//		dispatched when motion starts (this is at any motion start as the applicatin runs)
		// PenguinPop.MOTION_START
		//		dispatched when there has been no motion in motionInterval seconds (see getter setter methods)
		// Event.CHANGE
		//		dispatched when the emulator sends data 
		
		// METHODS
		// transposeValue(a:String, b:String):void
		// 		if the data coming in is not how you want to work with it
		// 		for instance, you want pitch to be -pitch or roll to be yaw...
		//		a is the original data which will be changed to values from b
		// 		properties you change are roll pitch yaw forward right down
		// 		you can also specify negatives like transposeValue("pitch", "-yaw");
		// 		see the method for more info
		// setView(v:String):void 
		//		sets the emulator view - v can be either "top" or "front"
		// setOrientation(o:String):void
		//		sets the orientation on the emulator - o can be "horizontal" or "vertical"
		// setFreedom(f:String):void 
		//		sets the freedom on the emulator - f can be "one" or "two"
		// dispose():void
		// 		stops tracking beats and removes listeners, etc.
		
		// PROPERTIES 	
		// view:String - sets or gets emulator view - default "top" other values: "front"
		// orientation:String - sets or gets emulator orientation default "vertical" other values: "horizontal"
		// roll:Number - (read only) clockwise rotation around the forward direction
		// pitch:Number - (read only) clockwise rotation around the right direction
		// yaw:Number - (read only) clockwise rotation around the down direction
		// forward:Number - (read only) direction of travel or user's view
		// right:Number - (read only) direction perpendicular to the forward direction and laterally to the right
		// down:Number - (read only) direction perpendicular to the forward and right and in the down direction
		// tiltUnits:String - (read only) default for the Penguin emulator is "degrees"
		// translationUnits:String - (read only) default for the Penguin emulator is "screens"
		// xmlData:XML - (read only) - the full XML from the emulator
		// transposeList:Array - sets or gets a list of transpositions (alternative to transposeValue method)				
		// motionInterval:Number - sets or gets seconds of no motion before the STOP_MOTION event is triggered
	
		// CONSTANTS
		// MOTION_START:String - static constant (Penguin.MOTION_START) for motion start event
		// MOTION_STOP:String - static constant (Penguin.MOTION_STOP) for motion stop event		
		
		public static const MOTION_START:String = "motion start";
		public static const MOTION_STOP:String = "motion stop";
		
		public var view:String;
		public var orientation:String;
		public var roll:Number = 0;
		public var pitch:Number = 0;
		public var yaw:Number = 0;
		public var forward:Number = 0;
		public var right:Number = 0;
		public var down:Number = 0;
		public var tiltUnits:String = "degrees";
		public var translationUnits:String = "screens";
		public var xmlData:XML;		
		public var transposeList:Array;
		
		private var myConnectionSend:LocalConnection = new LocalConnection(); 
		private var myConnectionReceive:LocalConnection = new LocalConnection(); 		
		private var dataNames:Array = ["pitch", "roll", "yaw", "forward", "right", "down"];
		private var disposeCheck = false;
		private var myView:String;
		private var myOrientation:String;
		private var myFreedom:String;	
				
		// motion start and stop variables
		private var motionState:String = PenguinPop.MOTION_START;
		private var motionLast:Array = [0,0,0,0,0,0];
		private var motionCount:Number = 0;			
		private var period:Number = 200; // ms between tilt data readings
		private var myMotionInterval:Number = 1;  // seconds of no motion until stop is determined
		private var loopModulus:Number; 
		
        public function PenguinPop(
					theView:String = "top",
					theOrientation:String = "vertical",
					theFreedom:String = "two"					
					) {	
			
			// PenguinPop communicates via LocalConnection
			myConnectionReceive.connect("PenguinPop"); 		
			myConnectionReceive.allowDomain("*");
			myConnectionReceive.client = this;
			
			myConnectionSend.addEventListener(StatusEvent.STATUS, onStatus);
			
			myView = theView;
			myOrientation = theOrientation;
			myFreedom = theFreedom;			
			
			transposeList = dataNames.concat();
			
			trace ("hi from PenguinPop");
			
        }
		
		public function emulatorReady() {
			setView(myView);
			setOrientation(myOrientation);
			setFreedom(myFreedom);
			dispatchEvent(new Event(Event.CONNECT));
		}
		
		private function onStatus(event:StatusEvent):void {
			switch (event.level) {
				case "status" :
					trace("LocalConnection.send() succeeded");
					break;
				case "error" :
					trace("LocalConnection.send() failed");
					break;
			}
		}		
		
		public function getTiltData(xmlData:XML) {			
			
			if (disposeCheck) {return;}			
			
			view = xmlData.view;
			orientation = xmlData.orientation;			
			roll = xmlData.tilt.@roll;
			pitch = xmlData.tilt.@pitch;
			yaw = xmlData.tilt.@yaw;
			forward = xmlData.translation.@forward;
			right = xmlData.translation.@right;
			down = xmlData.translation.@down;
			tiltUnits = xmlData.tilt.@units;
			translationUnits = xmlData.translation.@units;					
				
			// check for transposition
			if (dataNames.toString() != transposeList.toString()) {
				var len:uint = dataNames.length;
				var orig:Array = [];
				// store the originals
				for (var i:uint = 0; i < len; i++) {
					orig.push(this[dataNames[i]]);
				}
				var val:String;
				var val2:String;
				var sign:Number = 1;
				for (i = 0; i < len; i++) {
					if (dataNames[i] == transposeList[i]) {continue;}
					val = transposeList[i];
					val2 = val.replace(/-\s*/g, "");
					if (val != val2) {
						sign = -1;
					}
					this[dataNames[i]] = sign * orig[dataNames.indexOf(val2)];
				}
			}
			
			// check for motion stop and start
			if (motionState == PenguinPop.MOTION_STOP) {
				if (!compareArray([roll,pitch,yaw,forward,right,down], motionLast)) {
					motionState = PenguinPop.MOTION_START;
					motionCount = 0;					
					dispatchEvent(new Event(PenguinPop.MOTION_START));
				}
				motionLast = [roll,pitch,yaw,forward,right,down];
			} else {
				motionCount++;				
				if (motionCount % loopModulus == 0) {
					if (compareArray([roll,pitch,yaw,forward,right,down], motionLast)) {						
						motionState = PenguinPop.MOTION_STOP;
						dispatchEvent(new Event(PenguinPop.MOTION_STOP));
					}					
					motionLast = [roll,pitch,yaw,forward,right,down];
				}
			}			
			function compareArray(a1,a2) {
				var checkArray:Boolean = true;
				var len:Number = a1.length;
				for (var i:uint=0; i<len; i++) {
					if (a1[i] != a2[i]) {checkArray = false; break;}
				}				
				return checkArray;
			}
				
			dispatchEvent(new Event(Event.CHANGE));
		}
		
		public function setView(v:String):void {
			myConnectionSend.send("Emulator", "setView", myView);
		}
		public function setOrientation(o:String):void {
			myConnectionSend.send("Emulator", "setOrientation", myOrientation);
		}
		public function setFreedom(f:String):void {
			myConnectionSend.send("Emulator", "setFreedom", myFreedom);
		}
		
		public function transposeValue(a:String, b:String) {
			// a is the original data which will be changed to b
			// for instance to change pitch to be the value from yaw
			// transpose("pitch", "yaw")
			// this does not swap the values as you will rarely want to do that
			// original data names are pitch roll yaw forward right down
			// you can also change to a negative like so:
			// transpose("pitch","-pitch"); // or transpose("down","-forward");
			// now the transposeList stores the b value
			// that corresponds to the value in the dataNames
			// the transposeList is used to transpose the data in the doTilt function
			transposeList[dataNames.indexOf(a)] = b;
		}		
		
		public function set motionInterval(s:Number):void { // how many seconds does motion have to be the same for MOTION_STOP
			myMotionInterval = s;
			loopModulus = Math.max(1, Math.floor(myMotionInterval * 1000 / period));			
		}
		
		public function get motionInterval():Number {
			return myMotionInterval;
		}
		
		public function dispose() {
			disposeCheck = true; // just stops dispatching
		}		
		
    }
}