package net.flashpunk.graphics
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
import net.flashpunk.FP;
import net.flashpunk.Graphic;
/**
* Creates a pre-rotated Image strip to increase runtime performance for rotating graphics.
*/
public class PreRotation extends Image
{
/**
* Current angle to fetch the pre-rotated frame from.
*/
public var frameAngle:Number = 0;
/**
* Constructor.
* @param source The source image to be rotated.
* @param frameCount How many frames to use. More frames result in smoother rotations.
* @param smooth Make the rotated graphic appear less pixelly.
*/
public function PreRotation(source:Class, frameCount:uint = 36, smooth:Boolean = false)
{
var r:BitmapData = _rotated[source];
_frame = new Rectangle(0, 0, _size[source], _size[source]);
if (!r)
{
var temp:BitmapData = (new source).bitmapData,
size:uint = _size[source] = Math.ceil(FP.distance(0, 0, temp.width, temp.height));
_frame.width = _frame.height = size;
var width:uint = _frame.width * frameCount,
height:uint = _frame.height;
if (width > _MAX_WIDTH)
{
width = _MAX_WIDTH - (_MAX_WIDTH % _frame.width);
height = Math.ceil(frameCount / (width / _frame.width)) * _frame.height;
}
r = new BitmapData(width, height, true, 0);
var m:Matrix = FP.matrix,
a:Number = 0,
aa:Number = (Math.PI * 2) / -frameCount,
ox:uint = temp.width / 2,
oy:uint = temp.height / 2,
o:uint = _frame.width / 2,
x:uint = 0,
y:uint = 0;
while (y < height)
{
while (x < width)
{
m.identity();
m.translate(-ox, -oy);
m.rotate(a);
m.translate(o + x, o + y);
r.draw(temp, m, null, null, null, smooth);
x += _frame.width;
a += aa;
}
x = 0;
y += _frame.height;
}
}
_source = r;
_width = r.width;
_frameCount = frameCount;
super(_source, _frame);
}
/** @private Renders the PreRotated graphic. */
override public function render(target:BitmapData, point:Point, camera:Point):void
{
frameAngle %= 360;
if (frameAngle < 0) frameAngle += 360;
_current = uint(_frameCount * (frameAngle / 360));
if (_last != _current)
{
_last = _current;
_frame.x = _frame.width * _last;
_frame.y = uint(_frame.x / _width) * _frame.height;
_frame.x %= _width;
updateBuffer();
}
super.render(target, point, camera);
}
/** @private */ private var _width:uint;
/** @private */ private var _frame:Rectangle;
/** @private */ private var _frameCount:uint;
/** @private */ private var _last:int = -1;
/** @private */ private var _current:int = -1;
/** @private */ private static var _rotated:Dictionary = new Dictionary;
/** @private */ private static var _size:Dictionary = new Dictionary;
/** @private */ private static const _MAX_WIDTH:uint = 4000;
/** @private */ private static const _MAX_HEIGHT:uint = 4000;
}
}