Commits

Tao Chen  committed 5e6fd37

first

  • Participants

Comments (0)

Files changed (112)

File org/flixel/FlxBasic.as

+package org.flixel
+{	
+	/**
+	 * This is a useful "generic" Flixel object.
+	 * Both <code>FlxObject</code> and <code>FlxGroup</code> extend this class,
+	 * as do the plugins.  Has no size, position or graphical data.
+	 * 
+	 * @author	Adam Atomic
+	 */
+	public class FlxBasic
+	{
+		static internal var _ACTIVECOUNT:uint;
+		static internal var _VISIBLECOUNT:uint;
+
+		/**
+		 * IDs seem like they could be pretty useful, huh?
+		 * They're not actually used for anything yet though.
+		 */
+		public var ID:int;
+		/**
+		 * Controls whether <code>update()</code> and <code>draw()</code> are automatically called by FlxState/FlxGroup.
+		 */
+		public var exists:Boolean;
+		/**
+		 * Controls whether <code>update()</code> is automatically called by FlxState/FlxGroup.
+		 */
+		public var active:Boolean;
+		/**
+		 * Controls whether <code>draw()</code> is automatically called by FlxState/FlxGroup.
+		 */
+		public var visible:Boolean;
+		/**
+		 * Useful state for many game objects - "dead" (!alive) vs alive.
+		 * <code>kill()</code> and <code>revive()</code> both flip this switch (along with exists, but you can override that).
+		 */
+		public var alive:Boolean;
+		/**
+		 * An array of camera objects that this object will use during <code>draw()</code>.
+		 * This value will initialize itself during the first draw to automatically
+		 * point at the main camera list out in <code>FlxG</code> unless you already set it.
+		 * You can also change it afterward too, very flexible!
+		 */
+		public var cameras:Array;
+		/**
+		 * Setting this to true will prevent the object from appearing
+		 * when the visual debug mode in the debugger overlay is toggled on.
+		 */
+		public var ignoreDrawDebug:Boolean;
+		
+		/**
+		 * Instantiate the basic flixel object.
+		 */
+		public function FlxBasic()
+		{
+			ID = -1;
+			exists = true;
+			active = true;
+			visible = true;
+			alive = true;
+			ignoreDrawDebug = false;
+		}
+
+		/**
+		 * Override this function to null out variables or manually call
+		 * <code>destroy()</code> on class members if necessary.
+		 * Don't forget to call <code>super.destroy()</code>!
+		 */
+		public function destroy():void {}
+		
+		/**
+		 * Pre-update is called right before <code>update()</code> on each object in the game loop.
+		 */
+		public function preUpdate():void
+		{
+			_ACTIVECOUNT++;
+		}
+		
+		/**
+		 * Override this function to update your class's position and appearance.
+		 * This is where most of your game rules and behavioral code will go.
+		 */
+		public function update():void
+		{
+		}
+		
+		/**
+		 * Post-update is called right after <code>update()</code> on each object in the game loop.
+		 */
+		public function postUpdate():void
+		{
+		}
+		
+		/**
+		 * Override this function to control how the object is drawn.
+		 * Overriding <code>draw()</code> is rarely necessary, but can be very useful.
+		 */
+		public function draw():void
+		{
+			if(cameras == null)
+				cameras = FlxG.cameras;
+			var camera:FlxCamera;
+			var i:uint = 0;
+			var l:uint = cameras.length;
+			while(i < l)
+			{
+				camera = cameras[i++];
+				_VISIBLECOUNT++;
+				if(FlxG.visualDebug && !ignoreDrawDebug)
+					drawDebug(camera);
+			}
+		}
+		
+		/**
+		 * Override this function to draw custom "debug mode" graphics to the
+		 * specified camera while the debugger's visual mode is toggled on.
+		 * 
+		 * @param	Camera	Which camera to draw the debug visuals to.
+		 */
+		public function drawDebug(Camera:FlxCamera=null):void
+		{
+		}
+		
+		/**
+		 * Handy function for "killing" game objects.
+		 * Default behavior is to flag them as nonexistent AND dead.
+		 * However, if you want the "corpse" to remain in the game,
+		 * like to animate an effect or whatever, you should override this,
+		 * setting only alive to false, and leaving exists true.
+		 */
+		public function kill():void
+		{
+			alive = false;
+			exists = false;
+		}
+		
+		/**
+		 * Handy function for bringing game objects "back to life". Just sets alive and exists back to true.
+		 * In practice, this function is most often called by <code>FlxObject.reset()</code>.
+		 */
+		public function revive():void
+		{
+			alive = true;
+			exists = true;
+		}
+		
+		/**
+		 * Convert object to readable string name.  Useful for debugging, save games, etc.
+		 */
+		public function toString():String
+		{
+			return FlxU.getClassName(this,true);
+		}
+	}
+}

File org/flixel/FlxButton.as

+package org.flixel
+{
+	import flash.events.MouseEvent;
+	
+	/**
+	 * A simple button class that calls a function when clicked by the mouse.
+	 * 
+	 * @author	Adam Atomic
+	 */
+	public class FlxButton extends FlxSprite
+	{
+		[Embed(source="data/button.png")] protected var ImgDefaultButton:Class;
+		[Embed(source="data/beep.mp3")] protected var SndBeep:Class;
+		
+		/**
+		 * Used with public variable <code>status</code>, means not highlighted or pressed.
+		 */
+		static public var NORMAL:uint = 0;
+		/**
+		 * Used with public variable <code>status</code>, means highlighted (usually from mouse over).
+		 */
+		static public var HIGHLIGHT:uint = 1;
+		/**
+		 * Used with public variable <code>status</code>, means pressed (usually from mouse click).
+		 */
+		static public var PRESSED:uint = 2;
+		
+		/**
+		 * The text that appears on the button.
+		 */
+		public var label:FlxText;
+		/**
+		 * Controls the offset (from top left) of the text from the button.
+		 */
+		public var labelOffset:FlxPoint;
+		/**
+		 * This function is called when the button is released.
+		 * We recommend assigning your main button behavior to this function
+		 * via the <code>FlxButton</code> constructor.
+		 */
+		public var onUp:Function;
+		/**
+		 * This function is called when the button is pressed down.
+		 */
+		public var onDown:Function;
+		/**
+		 * This function is called when the mouse goes over the button.
+		 */
+		public var onOver:Function;
+		/**
+		 * This function is called when the mouse leaves the button area.
+		 */
+		public var onOut:Function;
+		/**
+		 * Shows the current state of the button.
+		 */
+		public var status:uint;
+		/**
+		 * Set this to play a sound when the mouse goes over the button.
+		 * We recommend using the helper function setSounds()!
+		 */
+		public var soundOver:FlxSound;
+		/**
+		 * Set this to play a sound when the mouse leaves the button.
+		 * We recommend using the helper function setSounds()!
+		 */
+		public var soundOut:FlxSound;
+		/**
+		 * Set this to play a sound when the button is pressed down.
+		 * We recommend using the helper function setSounds()!
+		 */
+		public var soundDown:FlxSound;
+		/**
+		 * Set this to play a sound when the button is released.
+		 * We recommend using the helper function setSounds()!
+		 */
+		public var soundUp:FlxSound;
+
+		/**
+		 * Used for checkbox-style behavior.
+		 */
+		protected var _onToggle:Boolean;
+		
+		/**
+		 * Tracks whether or not the button is currently pressed.
+		 */
+		protected var _pressed:Boolean;
+		/**
+		 * Whether or not the button has initialized itself yet.
+		 */
+		protected var _initialized:Boolean;
+		
+		/**
+		 * Creates a new <code>FlxButton</code> object with a gray background
+		 * and a callback function on the UI thread.
+		 * 
+		 * @param	X			The X position of the button.
+		 * @param	Y			The Y position of the button.
+		 * @param	Label		The text that you want to appear on the button.
+		 * @param	OnClick		The function to call whenever the button is clicked.
+		 */
+		public function FlxButton(X:Number=0,Y:Number=0,Label:String=null,OnClick:Function=null)
+		{
+			super(X,Y);
+			if(Label != null)
+			{
+				label = new FlxText(0,0,80,Label);
+				label.setFormat(null,8,0x333333,"center");
+				labelOffset = new FlxPoint(-1,3);
+			}
+			loadGraphic(ImgDefaultButton,true,false,80,20);
+			
+			onUp = OnClick;
+			onDown = null;
+			onOut = null;
+			onOver = null;
+			
+			soundOver = null;
+			soundOut = null;
+			soundDown = null;
+			soundUp = null;
+
+			status = NORMAL;
+			_onToggle = false;
+			_pressed = false;
+			_initialized = false;
+		}
+		
+		/**
+		 * Called by the game state when state is changed (if this object belongs to the state)
+		 */
+		override public function destroy():void
+		{
+			if(FlxG.stage != null)
+				FlxG.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
+			if(label != null)
+			{
+				label.destroy();
+				label = null;
+			}
+			onUp = null;
+			onDown = null;
+			onOut = null;
+			onOver = null;
+			if(soundOver != null)
+				soundOver.destroy();
+			if(soundOut != null)
+				soundOut.destroy();
+			if(soundDown != null)
+				soundDown.destroy();
+			if(soundUp != null)
+				soundUp.destroy();
+			super.destroy();
+		}
+		
+		/**
+		 * Since button uses its own mouse handler for thread reasons,
+		 * we run a little pre-check here to make sure that we only add
+		 * the mouse handler when it is actually safe to do so.
+		 */
+		override public function preUpdate():void
+		{
+			super.preUpdate();
+			
+			if(!_initialized)
+			{
+				if(FlxG.stage != null)
+				{
+					FlxG.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
+					_initialized = true;
+				}
+			}
+		}
+		
+		/**
+		 * Called by the game loop automatically, handles mouseover and click detection.
+		 */
+		override public function update():void
+		{
+			updateButton(); //Basic button logic
+
+			//Default button appearance is to simply update
+			// the label appearance based on animation frame.
+			if(label == null)
+				return;
+			switch(frame)
+			{
+				case HIGHLIGHT:	//Extra behavior to accomodate checkbox logic.
+					label.alpha = 1.0;
+					break;
+				case PRESSED:
+					label.alpha = 0.5;
+					label.y++;
+					break;
+				case NORMAL:
+				default:
+					label.alpha = 0.8;
+					break;
+			}
+		}
+		
+		/**
+		 * Basic button update logic
+		 */
+		protected function updateButton():void
+		{
+			//Figure out if the button is highlighted or pressed or what
+			// (ignore checkbox behavior for now).
+			if(FlxG.mouse.visible)
+			{
+				if(cameras == null)
+					cameras = FlxG.cameras;
+				var camera:FlxCamera;
+				var i:uint = 0;
+				var l:uint = cameras.length;
+				var offAll:Boolean = true;
+				while(i < l)
+				{
+					camera = cameras[i++] as FlxCamera;
+					FlxG.mouse.getWorldPosition(camera,_point);
+					if(overlapsPoint(_point,true,camera))
+					{
+						offAll = false;
+						if(FlxG.mouse.justPressed())
+						{
+							status = PRESSED;
+							if(onDown != null)
+								onDown();
+							if(soundDown != null)
+								soundDown.play(true);
+						}
+						if(status == NORMAL)
+						{
+							status = HIGHLIGHT;
+							if(onOver != null)
+								onOver();
+							if(soundOver != null)
+								soundOver.play(true);
+						}
+					}
+				}
+				if(offAll)
+				{
+					if(status != NORMAL)
+					{
+						if(onOut != null)
+							onOut();
+						if(soundOut != null)
+							soundOut.play(true);
+					}
+					status = NORMAL;
+				}
+			}
+		
+			//Then if the label and/or the label offset exist,
+			// position them to match the button.
+			if(label != null)
+			{
+				label.x = x;
+				label.y = y;
+			}
+			if(labelOffset != null)
+			{
+				label.x += labelOffset.x;
+				label.y += labelOffset.y;
+			}
+			
+			//Then pick the appropriate frame of animation
+			if((status == HIGHLIGHT) && _onToggle)
+				frame = NORMAL;
+			else
+				frame = status;
+		}
+		
+		/**
+		 * Just draws the button graphic and text label to the screen.
+		 */
+		override public function draw():void
+		{
+			super.draw();
+			if(label != null)
+			{
+				label.scrollFactor = scrollFactor;
+				label.cameras = cameras;
+				label.draw();
+			}
+		}
+		
+		/**
+		 * Updates the size of the text field to match the button.
+		 */
+		override protected function resetHelpers():void
+		{
+			super.resetHelpers();
+			if(label != null)
+				label.width = width;
+		}
+		
+		/**
+		 * Set sounds to play during mouse-button interactions.
+		 * These operations can be done manually as well, and the public
+		 * sound variables can be used after this for more fine-tuning,
+		 * such as positional audio, etc.
+		 * 
+		 * @param SoundOver			What embedded sound effect to play when the mouse goes over the button. Default is null, or no sound.
+		 * @param SoundOverVolume	How load the that sound should be.
+		 * @param SoundOut			What embedded sound effect to play when the mouse leaves the button area. Default is null, or no sound.
+		 * @param SoundOutVolume	How load the that sound should be.
+		 * @param SoundDown			What embedded sound effect to play when the mouse presses the button down. Default is null, or no sound.
+		 * @param SoundDownVolume	How load the that sound should be.
+		 * @param SoundUp			What embedded sound effect to play when the mouse releases the button. Default is null, or no sound.
+		 * @param SoundUpVolume		How load the that sound should be.
+		 */
+		public function setSounds(SoundOver:Class=null, SoundOverVolume:Number=1.0, SoundOut:Class=null, SoundOutVolume:Number=1.0, SoundDown:Class=null, SoundDownVolume:Number=1.0, SoundUp:Class=null, SoundUpVolume:Number=1.0):void
+		{
+			if(SoundOver != null)
+				soundOver = FlxG.loadSound(SoundOver, SoundOverVolume);
+			if(SoundOut != null)
+				soundOut = FlxG.loadSound(SoundOut, SoundOutVolume);
+			if(SoundDown != null)
+				soundDown = FlxG.loadSound(SoundDown, SoundDownVolume);
+			if(SoundUp != null)
+				soundUp = FlxG.loadSound(SoundUp, SoundUpVolume);
+		}
+		
+		/**
+		 * Use this to toggle checkbox-style behavior.
+		 */
+		public function get on():Boolean
+		{
+			return _onToggle;
+		}
+		
+		/**
+		 * @private
+		 */
+		public function set on(On:Boolean):void
+		{
+			_onToggle = On;
+		}
+		
+		/**
+		 * Internal function for handling the actual callback call (for UI thread dependent calls like <code>FlxU.openURL()</code>).
+		 */
+		protected function onMouseUp(event:MouseEvent):void
+		{
+			if(!exists || !visible || !active || (status != PRESSED))
+				return;
+			if(onUp != null)
+				onUp();
+			if(soundUp != null)
+				soundUp.play(true);
+		}
+	}
+}

File org/flixel/FlxCamera.as

+package org.flixel
+{
+	import flash.display.Bitmap;
+	import flash.display.BitmapData;
+	import flash.display.Sprite;
+	import flash.geom.ColorTransform;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+
+	/**
+	 * The camera class is used to display the game's visuals in the Flash player.
+	 * By default one camera is created automatically, that is the same size as the Flash player.
+	 * You can add more cameras or even replace the main camera using utilities in <code>FlxG</code>.
+	 * 
+	 * @author Adam Atomic
+	 */
+	public class FlxCamera extends FlxBasic
+	{
+		/**
+		 * Camera "follow" style preset: camera has no deadzone, just tracks the focus object directly.
+		 */
+		static public const STYLE_LOCKON:uint = 0;
+		/**
+		 * Camera "follow" style preset: camera deadzone is narrow but tall.
+		 */
+		static public const STYLE_PLATFORMER:uint = 1;
+		/**
+		 * Camera "follow" style preset: camera deadzone is a medium-size square around the focus object.
+		 */
+		static public const STYLE_TOPDOWN:uint = 2;
+		/**
+		 * Camera "follow" style preset: camera deadzone is a small square around the focus object.
+		 */
+		static public const STYLE_TOPDOWN_TIGHT:uint = 3;
+		
+		/**
+		 * Camera "shake" effect preset: shake camera on both the X and Y axes.
+		 */
+		static public const SHAKE_BOTH_AXES:uint = 0;
+		/**
+		 * Camera "shake" effect preset: shake camera on the X axis only.
+		 */
+		static public const SHAKE_HORIZONTAL_ONLY:uint = 1;
+		/**
+		 * Camera "shake" effect preset: shake camera on the Y axis only.
+		 */
+		static public const SHAKE_VERTICAL_ONLY:uint = 2;
+		
+		/**
+		 * While you can alter the zoom of each camera after the fact,
+		 * this variable determines what value the camera will start at when created.
+		 */
+		static public var defaultZoom:Number;
+		
+		/**
+		 * The X position of this camera's display.  Zoom does NOT affect this number.
+		 * Measured in pixels from the left side of the flash window.
+		 */
+		public var x:Number;
+		/**
+		 * The Y position of this camera's display.  Zoom does NOT affect this number.
+		 * Measured in pixels from the top of the flash window.
+		 */
+		public var y:Number;
+		/**
+		 * How wide the camera display is, in game pixels.
+		 */
+		public var width:uint;
+		/**
+		 * How tall the camera display is, in game pixels.
+		 */
+		public var height:uint;
+		/**
+		 * Tells the camera to follow this <code>FlxObject</code> object around.
+		 */
+		public var target:FlxObject;
+		/**
+		 * You can assign a "dead zone" to the camera in order to better control its movement.
+		 * The camera will always keep the focus object inside the dead zone,
+		 * unless it is bumping up against the bounds rectangle's edges.
+		 * The deadzone's coordinates are measured from the camera's upper left corner in game pixels.
+		 * For rapid prototyping, you can use the preset deadzones (e.g. <code>STYLE_PLATFORMER</code>) with <code>follow()</code>.
+		 */
+		public var deadzone:FlxRect;
+		/**
+		 * The edges of the camera's range, i.e. where to stop scrolling.
+		 * Measured in game pixels and world coordinates.
+		 */
+		public var bounds:FlxRect;
+		
+		/**
+		 * Stores the basic parallax scrolling values.
+		 */
+		public var scroll:FlxPoint;
+		/**
+		 * The actual bitmap data of the camera display itself.
+		 */
+		public var buffer:BitmapData;
+		/**
+		 * The natural background color of the camera. Defaults to FlxG.bgColor.
+		 * NOTE: can be transparent for crazy FX!
+		 */
+		public var bgColor:uint;
+		/**
+		 * Sometimes it's easier to just work with a <code>FlxSprite</code> than it is to work
+		 * directly with the <code>BitmapData</code> buffer.  This sprite reference will
+		 * allow you to do exactly that.
+		 */
+		public var screen:FlxSprite;
+		
+		/**
+		 * Indicates how far the camera is zoomed in.
+		 */
+		protected var _zoom:Number;
+		/**
+		 * Internal, to help avoid costly allocations.
+		 */
+		protected var _point:FlxPoint;
+		/**
+		 * Internal, help with color transforming the flash bitmap.
+		 */
+		protected var _color:uint;
+		
+		/**
+		 * Internal, used to render buffer to screen space.
+		 */
+		protected var _flashBitmap:Bitmap;
+		/**
+		 * Internal, used to render buffer to screen space.
+		 */
+		internal var _flashSprite:Sprite;
+		/**
+		 * Internal, used to render buffer to screen space.
+		 */
+		internal var _flashOffsetX:Number;
+		/**
+		 * Internal, used to render buffer to screen space.
+		 */
+		internal var _flashOffsetY:Number;
+		/**
+		 * Internal, used to render buffer to screen space.
+		 */
+		protected var _flashRect:Rectangle;
+		/**
+		 * Internal, used to render buffer to screen space.
+		 */
+		protected var _flashPoint:Point;
+		/**
+		 * Internal, used to control the "flash" special effect.
+		 */
+		protected var _fxFlashColor:uint;
+		/**
+		 * Internal, used to control the "flash" special effect.
+		 */
+		protected var _fxFlashDuration:Number;
+		/**
+		 * Internal, used to control the "flash" special effect.
+		 */
+		protected var _fxFlashComplete:Function;
+		/**
+		 * Internal, used to control the "flash" special effect.
+		 */
+		protected var _fxFlashAlpha:Number;
+		/**
+		 * Internal, used to control the "fade" special effect.
+		 */
+		protected var _fxFadeColor:uint;
+		/**
+		 * Internal, used to control the "fade" special effect.
+		 */
+		protected var _fxFadeDuration:Number;
+		/**
+		 * Internal, used to control the "fade" special effect.
+		 */
+		protected var _fxFadeComplete:Function;
+		/**
+		 * Internal, used to control the "fade" special effect.
+		 */
+		protected var _fxFadeAlpha:Number;
+		/**
+		 * Internal, used to control the "shake" special effect.
+		 */
+		protected var _fxShakeIntensity:Number;
+		/**
+		 * Internal, used to control the "shake" special effect.
+		 */
+		protected var _fxShakeDuration:Number;
+		/**
+		 * Internal, used to control the "shake" special effect.
+		 */
+		protected var _fxShakeComplete:Function;
+		/**
+		 * Internal, used to control the "shake" special effect.
+		 */
+		protected var _fxShakeOffset:FlxPoint;
+		/**
+		 * Internal, used to control the "shake" special effect.
+		 */
+		protected var _fxShakeDirection:uint;
+		/**
+		 * Internal helper variable for doing better wipes/fills between renders.
+		 */
+		protected var _fill:BitmapData;
+		
+		/**
+		 * Instantiates a new camera at the specified location, with the specified size and zoom level.
+		 * 
+		 * @param X			X location of the camera's display in pixels. Uses native, 1:1 resolution, ignores zoom.
+		 * @param Y			Y location of the camera's display in pixels. Uses native, 1:1 resolution, ignores zoom.
+		 * @param Width		The width of the camera display in pixels.
+		 * @param Height	The height of the camera display in pixels.
+		 * @param Zoom		The initial zoom level of the camera.  A zoom level of 2 will make all pixels display at 2x resolution.
+		 */
+		public function FlxCamera(X:int,Y:int,Width:int,Height:int,Zoom:Number=0)
+		{
+			x = X;
+			y = Y;
+			width = Width;
+			height = Height;
+			target = null;
+			deadzone = null;
+			scroll = new FlxPoint();
+			_point = new FlxPoint();
+			bounds = null;
+			screen = new FlxSprite();
+			screen.makeGraphic(width,height,0,true);
+			screen.setOriginToCorner();
+			buffer = screen.pixels;
+			bgColor = FlxG.bgColor;
+			_color = 0xffffff;
+
+			_flashBitmap = new Bitmap(buffer);
+			_flashBitmap.x = -width*0.5;
+			_flashBitmap.y = -height*0.5;
+			_flashSprite = new Sprite();
+			zoom = Zoom; //sets the scale of flash sprite, which in turn loads flashoffset values
+			_flashOffsetX = width*0.5*zoom;
+			_flashOffsetY = height*0.5*zoom;
+			_flashSprite.x = x + _flashOffsetX;
+			_flashSprite.y = y + _flashOffsetY;
+			_flashSprite.addChild(_flashBitmap);
+			_flashRect = new Rectangle(0,0,width,height);
+			_flashPoint = new Point();
+			
+			_fxFlashColor = 0;
+			_fxFlashDuration = 0.0;
+			_fxFlashComplete = null;
+			_fxFlashAlpha = 0.0;
+			
+			_fxFadeColor = 0;
+			_fxFadeDuration = 0.0;
+			_fxFadeComplete = null;
+			_fxFadeAlpha = 0.0;
+			
+			_fxShakeIntensity = 0.0;
+			_fxShakeDuration = 0.0;
+			_fxShakeComplete = null;
+			_fxShakeOffset = new FlxPoint();
+			_fxShakeDirection = 0;
+			
+			_fill = new BitmapData(width,height,true,0);
+		}
+		
+		/**
+		 * Clean up memory.
+		 */
+		override public function destroy():void
+		{
+			screen.destroy();
+			screen = null;
+			target = null;
+			scroll = null;
+			deadzone = null;
+			bounds = null;
+			buffer = null;
+			_flashBitmap = null;
+			_flashRect = null;
+			_flashPoint = null;
+			_fxFlashComplete = null;
+			_fxFadeComplete = null;
+			_fxShakeComplete = null;
+			_fxShakeOffset = null;
+			_fill = null;
+		}
+		
+		/**
+		 * Updates the camera scroll as well as special effects like screen-shake or fades.
+		 */
+		override public function update():void
+		{
+			//Either follow the object closely, 
+			//or doublecheck our deadzone and update accordingly.
+			if(target != null)
+			{
+				if(deadzone == null)
+					focusOn(target.getMidpoint(_point));
+				else
+				{
+					var edge:Number;
+					var targetX:Number = target.x + ((target.x > 0)?0.0000001:-0.0000001);
+					var targetY:Number = target.y + ((target.y > 0)?0.0000001:-0.0000001);
+					
+					edge = targetX - deadzone.x;
+					if(scroll.x > edge)
+						scroll.x = edge;
+					edge = targetX + target.width - deadzone.x - deadzone.width;
+					if(scroll.x < edge)
+						scroll.x = edge;
+					
+					edge = targetY - deadzone.y;
+					if(scroll.y > edge)
+						scroll.y = edge;
+					edge = targetY + target.height - deadzone.y - deadzone.height;
+					if(scroll.y < edge)
+						scroll.y = edge;
+				}
+			}
+			
+			//Make sure we didn't go outside the camera's bounds
+			if(bounds != null)
+			{
+				if(scroll.x < bounds.left)
+					scroll.x = bounds.left;
+				if(scroll.x > bounds.right - width)
+					scroll.x = bounds.right - width;
+				if(scroll.y < bounds.top)
+					scroll.y = bounds.top;
+				if(scroll.y > bounds.bottom - height)
+					scroll.y = bounds.bottom - height;
+			}
+			
+			//Update the "flash" special effect
+			if(_fxFlashAlpha > 0.0)
+			{
+				_fxFlashAlpha -= FlxG.elapsed/_fxFlashDuration;
+				if((_fxFlashAlpha <= 0) && (_fxFlashComplete != null))
+					_fxFlashComplete();
+			}
+			
+			//Update the "fade" special effect
+			if((_fxFadeAlpha > 0.0) && (_fxFadeAlpha < 1.0))
+			{
+				_fxFadeAlpha += FlxG.elapsed/_fxFadeDuration;
+				if(_fxFadeAlpha >= 1.0)
+				{
+					_fxFadeAlpha = 1.0;
+					if(_fxFadeComplete != null)
+						_fxFadeComplete();
+				}
+			}
+			
+			//Update the "shake" special effect
+			if(_fxShakeDuration > 0)
+			{
+				_fxShakeDuration -= FlxG.elapsed;
+				if(_fxShakeDuration <= 0)
+				{
+					_fxShakeOffset.make();
+					if(_fxShakeComplete != null)
+						_fxShakeComplete();
+				}
+				else
+				{
+					if((_fxShakeDirection == SHAKE_BOTH_AXES) || (_fxShakeDirection == SHAKE_HORIZONTAL_ONLY))
+						_fxShakeOffset.x = (FlxG.random()*_fxShakeIntensity*width*2-_fxShakeIntensity*width)*_zoom;
+					if((_fxShakeDirection == SHAKE_BOTH_AXES) || (_fxShakeDirection == SHAKE_VERTICAL_ONLY))
+						_fxShakeOffset.y = (FlxG.random()*_fxShakeIntensity*height*2-_fxShakeIntensity*height)*_zoom;
+				}
+			}
+		}
+		
+		/**
+		 * Tells this camera object what <code>FlxObject</code> to track.
+		 * 
+		 * @param	Target		The object you want the camera to track.  Set to null to not follow anything.
+		 * @param	Style		Leverage one of the existing "deadzone" presets.  If you use a custom deadzone, ignore this parameter and manually specify the deadzone after calling <code>follow()</code>.
+		 */
+		public function follow(Target:FlxObject, Style:uint=STYLE_LOCKON):void
+		{
+			target = Target;
+			var helper:Number;
+			switch(Style)
+			{
+				case STYLE_PLATFORMER:
+					var w:Number = width/8;
+					var h:Number = height/3;
+					deadzone = new FlxRect((width-w)/2,(height-h)/2 - h*0.25,w,h);
+					break;
+				case STYLE_TOPDOWN:
+					helper = FlxU.max(width,height)/4;
+					deadzone = new FlxRect((width-helper)/2,(height-helper)/2,helper,helper);
+					break;
+				case STYLE_TOPDOWN_TIGHT:
+					helper = FlxU.max(width,height)/8;
+					deadzone = new FlxRect((width-helper)/2,(height-helper)/2,helper,helper);
+					break;
+				case STYLE_LOCKON:
+				default:
+					deadzone = null;
+					break;
+			}
+		}
+		
+		/**
+		 * Move the camera focus to this location instantly.
+		 * 
+		 * @param	Point		Where you want the camera to focus.
+		 */
+		public function focusOn(Point:FlxPoint):void
+		{
+			Point.x += (Point.x > 0)?0.0000001:-0.0000001;
+			Point.y += (Point.y > 0)?0.0000001:-0.0000001;
+			scroll.make(Point.x - width*0.5,Point.y - height*0.5);
+		}
+		
+		/**
+		 * Specify the boundaries of the level or where the camera is allowed to move.
+		 * 
+		 * @param	X				The smallest X value of your level (usually 0).
+		 * @param	Y				The smallest Y value of your level (usually 0).
+		 * @param	Width			The largest X value of your level (usually the level width).
+		 * @param	Height			The largest Y value of your level (usually the level height).
+		 * @param	UpdateWorld		Whether the global quad-tree's dimensions should be updated to match (default: false).
+		 */
+		public function setBounds(X:Number=0, Y:Number=0, Width:Number=0, Height:Number=0, UpdateWorld:Boolean=false):void
+		{
+			if(bounds == null)
+				bounds = new FlxRect();
+			bounds.make(X,Y,Width,Height);
+			if(UpdateWorld)
+				FlxG.worldBounds.copyFrom(bounds);
+			update();
+		}
+		
+		/**
+		 * The screen is filled with this color and gradually returns to normal.
+		 * 
+		 * @param	Color		The color you want to use.
+		 * @param	Duration	How long it takes for the flash to fade.
+		 * @param	OnComplete	A function you want to run when the flash finishes.
+		 * @param	Force		Force the effect to reset.
+		 */
+		public function flash(Color:uint=0xffffffff, Duration:Number=1, OnComplete:Function=null, Force:Boolean=false):void
+		{
+			if(!Force && (_fxFlashAlpha > 0.0))
+				return;
+			_fxFlashColor = Color;
+			if(Duration <= 0)
+				Duration = Number.MIN_VALUE;
+			_fxFlashDuration = Duration;
+			_fxFlashComplete = OnComplete;
+			_fxFlashAlpha = 1.0;
+		}
+		
+		/**
+		 * The screen is gradually filled with this color.
+		 * 
+		 * @param	Color		The color you want to use.
+		 * @param	Duration	How long it takes for the fade to finish.
+		 * @param	OnComplete	A function you want to run when the fade finishes.
+		 * @param	Force		Force the effect to reset.
+		 */
+		public function fade(Color:uint=0xff000000, Duration:Number=1, OnComplete:Function=null, Force:Boolean=false):void
+		{
+			if(!Force && (_fxFadeAlpha > 0.0))
+				return;
+			_fxFadeColor = Color;
+			if(Duration <= 0)
+				Duration = Number.MIN_VALUE;
+			_fxFadeDuration = Duration;
+			_fxFadeComplete = OnComplete;
+			_fxFadeAlpha = Number.MIN_VALUE;
+		}
+		
+		/**
+		 * A simple screen-shake effect.
+		 * 
+		 * @param	Intensity	Percentage of screen size representing the maximum distance that the screen can move while shaking.
+		 * @param	Duration	The length in seconds that the shaking effect should last.
+		 * @param	OnComplete	A function you want to run when the shake effect finishes.
+		 * @param	Force		Force the effect to reset (default = true, unlike flash() and fade()!).
+		 * @param	Direction	Whether to shake on both axes, just up and down, or just side to side (use class constants SHAKE_BOTH_AXES, SHAKE_VERTICAL_ONLY, or SHAKE_HORIZONTAL_ONLY).
+		 */
+		public function shake(Intensity:Number=0.05, Duration:Number=0.5, OnComplete:Function=null, Force:Boolean=true, Direction:uint=SHAKE_BOTH_AXES):void
+		{
+			if(!Force && ((_fxShakeOffset.x != 0) || (_fxShakeOffset.y != 0)))
+				return;
+			_fxShakeIntensity = Intensity;
+			_fxShakeDuration = Duration;
+			_fxShakeComplete = OnComplete;
+			_fxShakeDirection = Direction;
+			_fxShakeOffset.make();
+		}
+		
+		/**
+		 * Just turns off all the camera effects instantly.
+		 */
+		public function stopFX():void
+		{
+			_fxFlashAlpha = 0.0;
+			_fxFadeAlpha = 0.0;
+			_fxShakeDuration = 0;
+			_flashSprite.x = x + width*0.5;
+			_flashSprite.y = y + height*0.5;
+		}
+		
+		/**
+		 * Copy the bounds, focus object, and deadzone info from an existing camera.
+		 * 
+		 * @param	Camera	The camera you want to copy from.
+		 * 
+		 * @return	A reference to this <code>FlxCamera</code> object.
+		 */
+		public function copyFrom(Camera:FlxCamera):FlxCamera
+		{
+			if(Camera.bounds == null)
+				bounds = null;
+			else
+			{
+				if(bounds == null)
+					bounds = new FlxRect();
+				bounds.copyFrom(Camera.bounds);
+			}
+			target = Camera.target;
+			if(target != null)
+			{
+				if(Camera.deadzone == null)
+					deadzone = null;
+				else
+				{
+					if(deadzone == null)
+						deadzone = new FlxRect();
+					deadzone.copyFrom(Camera.deadzone);
+				}
+			}
+			return this;
+		}
+		
+		/**
+		 * The zoom level of this camera. 1 = 1:1, 2 = 2x zoom, etc.
+		 */
+		public function get zoom():Number
+		{
+			return _zoom;
+		}
+		
+		/**
+		 * @private
+		 */
+		public function set zoom(Zoom:Number):void
+		{
+			if(Zoom == 0)
+				_zoom = defaultZoom;
+			else
+				_zoom = Zoom;
+			setScale(_zoom,_zoom);
+		}
+		
+		/**
+		 * The alpha value of this camera display (a Number between 0.0 and 1.0).
+		 */
+		public function get alpha():Number
+		{
+			return _flashBitmap.alpha;
+		}
+		
+		/**
+		 * @private
+		 */
+		public function set alpha(Alpha:Number):void
+		{
+			_flashBitmap.alpha = Alpha;
+		}
+		
+		/**
+		 * The angle of the camera display (in degrees).
+		 * Currently yields weird display results,
+		 * since cameras aren't nested in an extra display object yet.
+		 */
+		public function get angle():Number
+		{
+			return _flashSprite.rotation;
+		}
+		
+		/**
+		 * @private
+		 */
+		public function set angle(Angle:Number):void
+		{
+			_flashSprite.rotation = Angle;
+		}
+		
+		/**
+		 * The color tint of the camera display.
+		 */
+		public function get color():uint
+		{
+			return _color;
+		}
+		
+		/**
+		 * @private
+		 */
+		public function set color(Color:uint):void
+		{
+			_color = Color;
+			var colorTransform:ColorTransform = _flashBitmap.transform.colorTransform;
+			colorTransform.redMultiplier = (_color>>16)*0.00392;
+			colorTransform.greenMultiplier = (_color>>8&0xff)*0.00392;
+			colorTransform.blueMultiplier = (_color&0xff)*0.00392;
+			_flashBitmap.transform.colorTransform = colorTransform;
+		}
+		
+		/**
+		 * Whether the camera display is smooth and filtered, or chunky and pixelated.
+		 * Default behavior is chunky-style.
+		 */
+		public function get antialiasing():Boolean
+		{
+			return _flashBitmap.smoothing;
+		}
+		
+		/**
+		 * @private
+		 */
+		public function set antialiasing(Antialiasing:Boolean):void
+		{
+			_flashBitmap.smoothing = Antialiasing;
+		}
+		
+		/**
+		 * The scale of the camera object, irrespective of zoom.
+		 * Currently yields weird display results,
+		 * since cameras aren't nested in an extra display object yet.
+		 */
+		public function getScale():FlxPoint
+		{
+			return _point.make(_flashSprite.scaleX,_flashSprite.scaleY);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function setScale(X:Number,Y:Number):void
+		{
+			_flashSprite.scaleX = X;
+			_flashSprite.scaleY = Y;
+		}
+		
+		/**
+		 * Fetches a reference to the Flash <code>Sprite</code> object
+		 * that contains the camera display in the Flash display list.
+		 * Uses include 3D projection, advanced display list modification, and more.
+		 * NOTE: We don't recommend modifying this directly unless you are
+		 * fairly experienced.  For simple changes to the camera display,
+		 * like scaling, rotation, and color tinting, we recommend
+		 * using the existing <code>FlxCamera</code> variables.
+		 * 
+		 * @return	A Flash <code>Sprite</code> object containing the camera display.
+		 */
+		public function getContainerSprite():Sprite
+		{
+			return _flashSprite;
+		}
+		
+		/**
+		 * Fill the camera with the specified color.
+		 * 
+		 * @param	Color		The color to fill with in 0xAARRGGBB hex format.
+		 * @param	BlendAlpha	Whether to blend the alpha value or just wipe the previous contents.  Default is true.
+		 */
+		public function fill(Color:uint,BlendAlpha:Boolean=true):void
+		{
+			_fill.fillRect(_flashRect,Color);
+			buffer.copyPixels(_fill,_flashRect,_flashPoint,null,null,BlendAlpha);
+		}
+		
+		/**
+		 * Internal helper function, handles the actual drawing of all the special effects.
+		 */
+		internal function drawFX():void
+		{
+			var alphaComponent:Number;
+			
+			//Draw the "flash" special effect onto the buffer
+			if(_fxFlashAlpha > 0.0)
+			{
+				alphaComponent = _fxFlashColor>>24;
+				fill((uint(((alphaComponent <= 0)?0xff:alphaComponent)*_fxFlashAlpha)<<24)+(_fxFlashColor&0x00ffffff));
+			}
+			
+			//Draw the "fade" special effect onto the buffer
+			if(_fxFadeAlpha > 0.0)
+			{
+				alphaComponent = _fxFadeColor>>24;
+				fill((uint(((alphaComponent <= 0)?0xff:alphaComponent)*_fxFadeAlpha)<<24)+(_fxFadeColor&0x00ffffff));
+			}
+			
+			if((_fxShakeOffset.x != 0) || (_fxShakeOffset.y != 0))
+			{
+				_flashSprite.x = x + _flashOffsetX + _fxShakeOffset.x;
+				_flashSprite.y = y + _flashOffsetY + _fxShakeOffset.y;
+			}
+		}
+	}
+}

File org/flixel/FlxEmitter.as

+package org.flixel
+{
+
+	/**
+	 * <code>FlxEmitter</code> is a lightweight particle emitter.
+	 * It can be used for one-time explosions or for
+	 * continuous fx like rain and fire.  <code>FlxEmitter</code>
+	 * is not optimized or anything; all it does is launch
+	 * <code>FlxParticle</code> objects out at set intervals
+	 * by setting their positions and velocities accordingly.
+	 * It is easy to use and relatively efficient,
+	 * relying on <code>FlxGroup</code>'s RECYCLE POWERS.
+	 * 
+	 * @author	Adam Atomic
+	 */
+	public class FlxEmitter extends FlxGroup
+	{
+		/**
+		 * The X position of the top left corner of the emitter in world space.
+		 */
+		public var x:Number;
+		/**
+		 * The Y position of the top left corner of emitter in world space.
+		 */
+		public var y:Number;
+		/**
+		 * The width of the emitter.  Particles can be randomly generated from anywhere within this box.
+		 */
+		public var width:Number;
+		/**
+		 * The height of the emitter.  Particles can be randomly generated from anywhere within this box.
+		 */
+		public var height:Number;
+		/**
+		 * The minimum possible velocity of a particle.
+		 * The default value is (-100,-100).
+		 */
+		public var minParticleSpeed:FlxPoint;
+		/**
+		 * The maximum possible velocity of a particle.
+		 * The default value is (100,100).
+		 */
+		public var maxParticleSpeed:FlxPoint;
+		/**
+		 * The X and Y drag component of particles launched from the emitter.
+		 */
+		public var particleDrag:FlxPoint;
+		/**
+		 * The minimum possible angular velocity of a particle.  The default value is -360.
+		 * NOTE: rotating particles are more expensive to draw than non-rotating ones!
+		 */
+		public var minRotation:Number;
+		/**
+		 * The maximum possible angular velocity of a particle.  The default value is 360.
+		 * NOTE: rotating particles are more expensive to draw than non-rotating ones!
+		 */
+		public var maxRotation:Number;
+		/**
+		 * Sets the <code>acceleration.y</code> member of each particle to this value on launch.
+		 */
+		public var gravity:Number;
+		/**
+		 * Determines whether the emitter is currently emitting particles.
+		 * It is totally safe to directly toggle this.
+		 */
+		public var on:Boolean;
+		/**
+		 * How often a particle is emitted (if emitter is started with Explode == false).
+		 */
+		public var frequency:Number;
+		/**
+		 * How long each particle lives once it is emitted.
+		 * Set lifespan to 'zero' for particles to live forever.
+		 */
+		public var lifespan:Number;
+		/**
+		 * How much each particle should bounce.  1 = full bounce, 0 = no bounce.
+		 */
+		public var bounce:Number;
+		/**
+		 * Set your own particle class type here.
+		 * Default is <code>FlxParticle</code>.
+		 */
+		public var particleClass:Class;
+		/**
+		 * Internal helper for deciding how many particles to launch.
+		 */
+		protected var _quantity:uint;
+		/**
+		 * Internal helper for the style of particle emission (all at once, or one at a time).
+		 */
+		protected var _explode:Boolean;
+		/**
+		 * Internal helper for deciding when to launch particles or kill them.
+		 */
+		protected var _timer:Number;
+		/**
+		 * Internal counter for figuring out how many particles to launch.
+		 */
+		protected var _counter:uint;
+		/**
+		 * Internal point object, handy for reusing for memory mgmt purposes.
+		 */
+		protected var _point:FlxPoint;
+		
+		/**
+		 * Creates a new <code>FlxEmitter</code> object at a specific position.
+		 * Does NOT automatically generate or attach particles!
+		 * 
+		 * @param	X		The X position of the emitter.
+		 * @param	Y		The Y position of the emitter.
+		 * @param	Size	Optional, specifies a maximum capacity for this emitter.
+		 */
+		public function FlxEmitter(X:Number=0, Y:Number=0, Size:Number=0)
+		{
+			super(Size);
+			x = X;
+			y = Y;
+			width = 0;
+			height = 0;
+			minParticleSpeed = new FlxPoint(-100,-100);
+			maxParticleSpeed = new FlxPoint(100,100);
+			minRotation = -360;
+			maxRotation = 360;
+			gravity = 0;
+			particleClass = null;
+			particleDrag = new FlxPoint();
+			frequency = 0.1;
+			lifespan = 3;
+			bounce = 0;
+			_quantity = 0;
+			_counter = 0;
+			_explode = true;
+			on = false;
+			_point = new FlxPoint();
+		}
+		
+		/**
+		 * Clean up memory.
+		 */
+		override public function destroy():void
+		{
+			minParticleSpeed = null;
+			maxParticleSpeed = null;
+			particleDrag = null;
+			particleClass = null;
+			_point = null;
+			super.destroy();
+		}
+		
+		/**
+		 * This function generates a new array of particle sprites to attach to the emitter.
+		 * 
+		 * @param	Graphics		If you opted to not pre-configure an array of FlxSprite objects, you can simply pass in a particle image or sprite sheet.
+		 * @param	Quantity		The number of particles to generate when using the "create from image" option.
+		 * @param	BakedRotations	How many frames of baked rotation to use (boosts performance).  Set to zero to not use baked rotations.
+		 * @param	Multiple		Whether the image in the Graphics param is a single particle or a bunch of particles (if it's a bunch, they need to be square!).
+		 * @param	Collide			Whether the particles should be flagged as not 'dead' (non-colliding particles are higher performance).  0 means no collisions, 0-1 controls scale of particle's bounding box.
+		 * 
+		 * @return	This FlxEmitter instance (nice for chaining stuff together, if you're into that).
+		 */
+		public function makeParticles(Graphics:Class, Quantity:uint=50, BakedRotations:uint=16, Multiple:Boolean=false, Collide:Number=0.8):FlxEmitter
+		{
+			maxSize = Quantity;
+			
+			var totalFrames:uint = 1;
+			if(Multiple)
+			{ 
+				var sprite:FlxSprite = new FlxSprite();
+				sprite.loadGraphic(Graphics,true);
+				totalFrames = sprite.frames;
+				sprite.destroy();
+			}
+
+			var randomFrame:uint;
+			var particle:FlxParticle;
+			var i:uint = 0;
+			while(i < Quantity)
+			{
+				if(particleClass == null)
+					particle = new FlxParticle();
+				else
+					particle = new particleClass();
+				if(Multiple)
+				{
+					randomFrame = FlxG.random()*totalFrames;
+					if(BakedRotations > 0)
+						particle.loadRotatedGraphic(Graphics,BakedRotations,randomFrame);
+					else
+					{
+						particle.loadGraphic(Graphics,true);
+						particle.frame = randomFrame;
+					}
+				}
+				else
+				{
+					if(BakedRotations > 0)
+						particle.loadRotatedGraphic(Graphics,BakedRotations);
+					else
+						particle.loadGraphic(Graphics);
+				}
+				if(Collide > 0)
+				{
+					particle.width *= Collide;
+					particle.height *= Collide;
+					particle.centerOffsets();
+				}
+				else
+					particle.allowCollisions = FlxObject.NONE;
+				particle.exists = false;
+				add(particle);
+				i++;
+			}
+			return this;
+		}
+		
+		/**
+		 * Called automatically by the game loop, decides when to launch particles and when to "die".
+		 */
+		override public function update():void
+		{
+			if(on)
+			{
+				if(_explode)
+				{
+					on = false;
+					var i:uint = 0;
+					var l:uint = _quantity;
+					if((l <= 0) || (l > length))
+						l = length;
+					while(i < l)
+					{
+						emitParticle();
+						i++;
+					}
+					_quantity = 0;
+				}
+				else
+				{
+					_timer += FlxG.elapsed;
+					while((frequency > 0) && (_timer > frequency) && on)
+					{
+						_timer -= frequency;
+						emitParticle();
+						if((_quantity > 0) && (++_counter >= _quantity))
+						{
+							on = false;
+							_quantity = 0;
+						}
+					}
+				}
+			}
+			super.update();
+		}
+		
+		/**
+		 * Call this function to turn off all the particles and the emitter.
+		 */
+		override public function kill():void
+		{
+			on = false;
+			super.kill();
+		}
+		
+		/**
+		 * Call this function to start emitting particles.
+		 * 
+		 * @param	Explode		Whether the particles should all burst out at once.
+		 * @param	Lifespan	How long each particle lives once emitted. 0 = forever.
+		 * @param	Frequency	Ignored if Explode is set to true. Frequency is how often to emit a particle. 0 = never emit, 0.1 = 1 particle every 0.1 seconds, 5 = 1 particle every 5 seconds.
+		 * @param	Quantity	How many particles to launch. 0 = "all of the particles".
+		 */
+		public function start(Explode:Boolean=true,Lifespan:Number=0,Frequency:Number=0.1,Quantity:uint=0):void
+		{
+			revive();
+			visible = true;
+			on = true;
+			
+			_explode = Explode;
+			lifespan = Lifespan;
+			frequency = Frequency;
+			_quantity += Quantity;
+			
+			_counter = 0;
+			_timer = 0;
+		}
+		
+		/**
+		 * This function can be used both internally and externally to emit the next particle.
+		 */
+		public function emitParticle():void
+		{
+			var particle:FlxParticle = recycle(FlxParticle) as FlxParticle;
+			particle.lifespan = lifespan;
+			particle.elasticity = bounce;
+			particle.reset(x - (particle.width>>1) + FlxG.random()*width, y - (particle.height>>1) + FlxG.random()*height);
+			particle.visible = true;
+			
+			if(minParticleSpeed.x != maxParticleSpeed.x)
+				particle.velocity.x = minParticleSpeed.x + FlxG.random()*(maxParticleSpeed.x-minParticleSpeed.x);
+			else
+				particle.velocity.x = minParticleSpeed.x;
+			if(minParticleSpeed.y != maxParticleSpeed.y)
+				particle.velocity.y = minParticleSpeed.y + FlxG.random()*(maxParticleSpeed.y-minParticleSpeed.y);
+			else
+				particle.velocity.y = minParticleSpeed.y;
+			particle.acceleration.y = gravity;
+			
+			if(minRotation != maxRotation)
+				particle.angularVelocity = minRotation + FlxG.random()*(maxRotation-minRotation);
+			else
+				particle.angularVelocity = minRotation;
+			if(particle.angularVelocity != 0)
+				particle.angle = FlxG.random()*360-180;
+			
+			particle.drag.x = particleDrag.x;
+			particle.drag.y = particleDrag.y;
+			particle.onEmit();
+		}
+		
+		/**
+		 * A more compact way of setting the width and height of the emitter.
+		 * 
+		 * @param	Width	The desired width of the emitter (particles are spawned randomly within these dimensions).
+		 * @param	Height	The desired height of the emitter.
+		 */
+		public function setSize(Width:uint,Height:uint):void
+		{
+			width = Width;
+			height = Height;
+		}
+		
+		/**
+		 * A more compact way of setting the X velocity range of the emitter.
+		 * 
+		 * @param	Min		The minimum value for this range.
+		 * @param	Max		The maximum value for this range.
+		 */
+		public function setXSpeed(Min:Number=0,Max:Number=0):void
+		{
+			minParticleSpeed.x = Min;
+			maxParticleSpeed.x = Max;
+		}
+		
+		/**
+		 * A more compact way of setting the Y velocity range of the emitter.
+		 * 
+		 * @param	Min		The minimum value for this range.
+		 * @param	Max		The maximum value for this range.
+		 */
+		public function setYSpeed(Min:Number=0,Max:Number=0):void
+		{
+			minParticleSpeed.y = Min;
+			maxParticleSpeed.y = Max;
+		}
+		
+		/**
+		 * A more compact way of setting the angular velocity constraints of the emitter.
+		 * 
+		 * @param	Min		The minimum value for this range.
+		 * @param	Max		The maximum value for this range.
+		 */
+		public function setRotation(Min:Number=0,Max:Number=0):void
+		{
+			minRotation = Min;
+			maxRotation = Max;
+		}
+		
+		/**
+		 * Change the emitter's midpoint to match the midpoint of a <code>FlxObject</code>.
+		 * 
+		 * @param	Object		The <code>FlxObject</code> that you want to sync up with.
+		 */
+		public function at(Object:FlxObject):void
+		{
+			Object.getMidpoint(_point);
+			x = _point.x - (width>>1);
+			y = _point.y - (height>>1);
+		}
+	}
+}

File org/flixel/FlxG.as

+package org.flixel
+{
+	import flash.display.BitmapData;
+	import flash.display.Graphics;
+	import flash.display.Sprite;
+	import flash.display.Stage;
+	import flash.geom.Matrix;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	
+	import org.flixel.plugin.DebugPathDisplay;
+	import org.flixel.plugin.TimerManager;
+	import org.flixel.system.FlxDebugger;
+	import org.flixel.system.FlxQuadTree;
+	import org.flixel.system.input.*;
+	
+	/**
+	 * This is a global helper class full of useful functions for audio,
+	 * input, basic info, and the camera system among other things.
+	 * Utilities for maths and color and things can be found in <code>FlxU</code>.
+	 * <code>FlxG</code> is specifically for Flixel-specific properties.
+	 * 
+	 * @author	Adam Atomic
+	 */
+	public class FlxG
+	{
+		/**
+		 * If you build and maintain your own version of flixel,
+		 * you can give it your own name here.
+		 */
+		static public var LIBRARY_NAME:String = "flixel";
+		/**
+		 * Assign a major version to your library.
+		 * Appears before the decimal in the console.
+		 */
+		static public var LIBRARY_MAJOR_VERSION:uint = 2;
+		/**
+		 * Assign a minor version to your library.
+		 * Appears after the decimal in the console.
+		 */
+		static public var LIBRARY_MINOR_VERSION:uint = 55;
+		
+		/**
+		 * Debugger overlay layout preset: Wide but low windows at the bottom of the screen.
+		 */
+		static public const DEBUGGER_STANDARD:uint = 0;
+		/**
+		 * Debugger overlay layout preset: Tiny windows in the screen corners.
+		 */
+		static public const DEBUGGER_MICRO:uint = 1;
+		/**
+		 * Debugger overlay layout preset: Large windows taking up bottom half of screen.
+		 */
+		static public const DEBUGGER_BIG:uint = 2;
+		/**
+		 * Debugger overlay layout preset: Wide but low windows at the top of the screen.
+		 */
+		static public const DEBUGGER_TOP:uint = 3;
+		/**
+		 * Debugger overlay layout preset: Large windows taking up left third of screen.
+		 */
+		static public const DEBUGGER_LEFT:uint = 4;
+		/**
+		 * Debugger overlay layout preset: Large windows taking up right third of screen.
+		 */
+		static public const DEBUGGER_RIGHT:uint = 5;
+		
+		/**
+		 * Some handy color presets.  Less glaring than pure RGB full values.
+		 * Primarily used in the visual debugger mode for bounding box displays.
+		 * Red is used to indicate an active, movable, solid object.
+		 */
+		static public const RED:uint = 0xffff0012;
+		/**
+		 * Green is used to indicate solid but immovable objects.
+		 */
+		static public const GREEN:uint = 0xff00f225;
+		/**
+		 * Blue is used to indicate non-solid objects.
+		 */
+		static public const BLUE:uint = 0xff0090e9;
+		/**
+		 * Pink is used to indicate objects that are only partially solid, like one-way platforms.
+		 */
+		static public const PINK:uint = 0xfff01eff;
+		/**
+		 * White... for white stuff.
+		 */
+		static public const WHITE:uint = 0xffffffff;
+		/**
+		 * And black too.
+		 */
+		static public const BLACK:uint = 0xff000000;
+
+		/**
+		 * Internal tracker for game object.
+		 */
+		static internal var _game:FlxGame;
+		/**
+		 * Handy shared variable for implementing your own pause behavior.
+		 */
+		static public var paused:Boolean;
+		/**
+		 * Whether you are running in Debug or Release mode.
+		 * Set automatically by <code>FlxPreloader</code> during startup.
+		 */
+		static public var debug:Boolean;
+		
+		/**
+		 * Represents the amount of time in seconds that passed since last frame.
+		 */
+		static public var elapsed:Number;
+		/**
+		 * How fast or slow time should pass in the game; default is 1.0.
+		 */
+		static public var timeScale:Number;
+		/**
+		 * The width of the screen in game pixels.
+		 */
+		static public var width:uint;
+		/**
+		 * The height of the screen in game pixels.
+		 */
+		static public var height:uint;
+		/**
+		 * The dimensions of the game world, used by the quad tree for collisions and overlap checks.
+		 */
+		static public var worldBounds:FlxRect;
+		/**
+		 * How many times the quad tree should divide the world on each axis.
+		 * Generally, sparse collisions can have fewer divisons,
+		 * while denser collision activity usually profits from more.
+		 * Default value is 6.
+		 */
+		static public var worldDivisions:uint;
+		/**
+		 * Whether to show visual debug displays or not.
+		 * Default = false.
+		 */
+		static public var visualDebug:Boolean;
+		/**
+		 * Setting this to true will disable/skip stuff that isn't necessary for mobile platforms like Android. [BETA]
+		 */
+		static public var mobile:Boolean; 
+		/**
+		 * The global random number generator seed (for deterministic behavior in recordings and saves).
+		 */
+		static public var globalSeed:Number;
+		/**
+		 * <code>FlxG.levels</code> and <code>FlxG.scores</code> are generic
+		 * global variables that can be used for various cross-state stuff.
+		 */
+		static public var levels:Array;
+		static public var level:int;
+		static public var scores:Array;
+		static public var score:int;
+		/**
+		 * <code>FlxG.saves</code> is a generic bucket for storing
+		 * FlxSaves so you can access them whenever you want.
+		 */
+		static public var saves:Array; 
+		static public var save:int;
+
+		/**
+		 * A reference to a <code>FlxMouse</code> object.  Important for input!
+		 */
+		static public var mouse:Mouse;
+		/**
+		 * A reference to a <code>FlxKeyboard</code> object.  Important for input!
+		 */
+		static public var keys:Keyboard;
+		
+		/**
+		 * A handy container for a background music object.
+		 */
+		static public var music:FlxSound;
+		/**
+		 * A list of all the sounds being played in the game.
+		 */
+		static public var sounds:FlxGroup;
+		/**
+		 * Whether or not the game sounds are muted.
+		 */
+		static public var mute:Boolean;
+		/**
+		 * Internal volume level, used for global sound control.
+		 */
+		static protected var _volume:Number;
+
+		/**
+		 * An array of <code>FlxCamera</code> objects that are used to draw stuff.
+		 * By default flixel creates one camera the size of the screen.
+		 */
+		static public var cameras:Array;
+		/**
+		 * By default this just refers to the first entry in the cameras array
+		 * declared above, but you can do what you like with it.
+		 */
+		static public var camera:FlxCamera;
+		/**
+		 * Allows you to possibly slightly optimize the rendering process IF
+		 * you are not doing any pre-processing in your game state's <code>draw()</code> call.
+		 * @default false
+		 */
+		static public var useBufferLocking:Boolean;
+		/**
+		 * Internal helper variable for clearing the cameras each frame.
+		 */
+		static protected var _cameraRect:Rectangle;
+		
+		/**
+		 * An array container for plugins.
+		 * By default flixel uses a couple of plugins:
+		 * DebugPathDisplay, and TimerManager.
+		 */
+		 static public var plugins:Array;
+		 
+		/**
+		 * Set this hook to get a callback whenever the volume changes.
+		 * Function should take the form <code>myVolumeHandler(Volume:Number)</code>.
+		 */
+		static public var volumeHandler:Function;
+		
+		/**
+		 * Useful helper objects for doing Flash-specific rendering.
+		 * Primarily used for "debug visuals" like drawing bounding boxes directly to the screen buffer.
+		 */
+		static public var flashGfxSprite:Sprite;
+		static public var flashGfx:Graphics;
+
+		/**
+		 * Internal storage system to prevent graphics from being used repeatedly in memory.
+		 */
+		static protected var _cache:Object;
+
+		static public function getLibraryName():String
+		{
+			return FlxG.LIBRARY_NAME + " v" + FlxG.LIBRARY_MAJOR_VERSION + "." + FlxG.LIBRARY_MINOR_VERSION;
+		}
+		
+		/**
+		 * Log data to the debugger.
+		 * 
+		 * @param	Data		Anything you want to log to the console.
+		 */
+		static public function log(Data:Object):void
+		{
+			if((_game != null) && (_game._debugger != null))
+				_game._debugger.log.add((Data == null)?"ERROR: null object":((Data is Array)?FlxU.formatArray(Data as Array):Data.toString()));
+		}
+		
+		/**
+		 * Add a variable to the watch list in the debugger.
+		 * This lets you see the value of the variable all the time.
+		 * 
+		 * @param	AnyObject		A reference to any object in your game, e.g. Player or Robot or this.
+		 * @param	VariableName	The name of the variable you want to watch, in quotes, as a string: e.g. "speed" or "health".
+		 * @param	DisplayName		Optional, display your own string instead of the class name + variable name: e.g. "enemy count".
+		 */
+		static public function watch(AnyObject:Object,VariableName:String,DisplayName:String=null):void
+		{
+			if((_game != null) && (_game._debugger != null))
+				_game._debugger.watch.add(AnyObject,VariableName,DisplayName);
+		}
+		
+		/**
+		 * Remove a variable from the watch list in the debugger.
+		 * Don't pass a Variable Name to remove all watched variables for the specified object.
+		 * 
+		 * @param	AnyObject		A reference to any object in your game, e.g. Player or Robot or this.
+		 * @param	VariableName	The name of the variable you want to watch, in quotes, as a string: e.g. "speed" or "health".
+		 */
+		static public function unwatch(AnyObject:Object,VariableName:String=null):void
+		{
+			if((_game != null) && (_game._debugger != null))
+				_game._debugger.watch.remove(AnyObject,VariableName);
+		}
+		
+		/**
+		 * How many times you want your game to update each second.
+		 * More updates usually means better collisions and smoother motion.
+		 * NOTE: This is NOT the same thing as the Flash Player framerate!
+		 */
+		static public function get framerate():Number
+		{
+			return 1000/_game._step;
+		}
+		
+		/**
+		 * @private
+		 */
+		static public function set framerate(Framerate:Number):void
+		{
+			_game._step = 1000/Framerate;
+			if(_game._maxAccumulation < _game._step)
+				_game._maxAccumulation = _game._step;
+		}
+		
+		/**
+		 * How many times you want your game to update each second.
+		 * More updates usually means better collisions and smoother motion.
+		 * NOTE: This is NOT the same thing as the Flash Player framerate!
+		 */
+		static public function get flashFramerate():Number
+		{
+			if(_game.root != null)
+				return _game.stage.frameRate;
+			else
+				return 0;
+		}
+		
+		/**
+		 * @private
+		 */
+		static public function set flashFramerate(Framerate:Number):void
+		{
+			_game._flashFramerate = Framerate;
+			if(_game.root != null)
+				_game.stage.frameRate = _game._flashFramerate;
+			_game._maxAccumulation = 2000/_game._flashFramerate - 1;
+			if(_game._maxAccumulation < _game._step)
+				_game._maxAccumulation = _game._step;
+		}
+		
+		/**
+		 * Generates a random number.  Deterministic, meaning safe
+		 * to use if you want to record replays in random environments.
+		 * 
+		 * @return	A <code>Number</code> between 0 and 1.
+		 */
+		static public function random():Number
+		{
+			return globalSeed = FlxU.srand(globalSeed);
+		}
+		
+		/**
+		 * Shuffles the entries in an array into a new random order.
+		 * <code>FlxG.shuffle()</code> is deterministic and safe for use with replays/recordings.
+		 * HOWEVER, <code>FlxU.shuffle()</code> is NOT deterministic and unsafe for use with replays/recordings.
+		 * 
+		 * @param	A				A Flash <code>Array</code> object containing...stuff.
+		 * @param	HowManyTimes	How many swaps to perform during the shuffle operation.  Good rule of thumb is 2-4 times as many objects are in the list.
+		 * 
+		 * @return	The same Flash <code>Array</code> object that you passed in in the first place.
+		 */
+		static public function shuffle(Objects:Array,HowManyTimes:uint):Array
+		{
+			var i:uint = 0;
+			var index1:uint;
+			var index2:uint;
+			var object:Object;
+			while(i < HowManyTimes)
+			{
+				index1 = FlxG.random()*Objects.length;
+				index2 = FlxG.random()*Objects.length;
+				object = Objects[index2];
+				Objects[index2] = Objects[index1];
+				Objects[index1] = object;
+				i++;
+			}
+			return Objects;
+		}
+		
+		/**
+		 * Fetch a random entry from the given array.
+		 * Will return null if random selection is missing, or array has no entries.
+		 * <code>FlxG.getRandom()</code> is deterministic and safe for use with replays/recordings.
+		 * HOWEVER, <code>FlxU.getRandom()</code> is NOT deterministic and unsafe for use with replays/recordings.
+		 * 
+		 * @param	Objects		A Flash array of objects.
+		 * @param	StartIndex	Optional offset off the front of the array. Default value is 0, or the beginning of the array.
+		 * @param	Length		Optional restriction on the number of values you want to randomly select from.
+		 * 
+		 * @return	The random object that was selected.
+		 */
+		static public function getRandom(Objects:Array,StartIndex:uint=0,Length:uint=0):Object
+		{
+			if(Objects != null)
+			{
+				var l:uint = Length;
+				if((l == 0) || (l > Objects.length - StartIndex))
+					l = Objects.length - StartIndex;
+				if(l > 0)
+					return Objects[StartIndex + uint(FlxG.random()*l)];
+			}
+			return null;
+		}
+		
+		/**
+		 * Load replay data from a string and play it back.
+		 * 
+		 * @param	Data		The replay that you want to load.
+		 * @param	State		Optional parameter: if you recorded a state-specific demo or cutscene, pass a new instance of that state here.
+		 * @param	CancelKeys	Optional parameter: an array of string names of keys (see FlxKeyboard) that can be pressed to cancel the playback, e.g. ["ESCAPE","ENTER"].  Also accepts 2 custom key names: "ANY" and "MOUSE" (fairly self-explanatory I hope!).
+		 * @param	Timeout		Optional parameter: set a time limit for the replay.  CancelKeys will override this if pressed.
+		 * @param	Callback	Optional parameter: if set, called when the replay finishes.  Running to the end, CancelKeys, and Timeout will all trigger Callback(), but only once, and CancelKeys and Timeout will NOT call FlxG.stopReplay() if Callback is set!
+		 */
+		static public function loadReplay(Data:String,State:FlxState=null,CancelKeys:Array=null,Timeout:Number=0,Callback:Function=null):void
+		{
+			_game._replay.load(Data);
+			if(State == null)
+				FlxG.resetGame();
+			else
+				FlxG.switchState(State);
+			_game._replayCancelKeys = CancelKeys;
+			_game._replayTimer = Timeout*1000;
+			_game._replayCallback = Callback;
+			_game._replayRequested = true;
+		}
+		
+		/**