FlashPunk Forums

September 02, 2010 *
News:
 



Pages: [1]
  Print  
Author Topic: net.flashpunk.graphics.SpritemapRotated  (Read 290 times)
p0wn
....................
*
Posts: 14


View Profile Email
« on: June 10, 2010 »

Pre Rotated Spritemap

What it does: creates an animatable spritemap that is also fully rotatable. Essentially it for loops through each sprite, and creates a row of that sprite rotated how ever many times you want.

It also caches each one, so if you have 30 enemies on screen, they all draw from the same bitmapdata, rather  than having 30 1200x1200 bmps in memory.

This is very very raw, undocumented, early code. I'm posting it for anyone who might enjoy having this feature, and will give help/update when I can.


Modifications required:

In order for this to work you must create an interface(normal class as file) in a folder inside net.flashpunk.graphics called interfaces

Create an as file called IAnimated.as
copy and paste this code inside:

Code:
package net.flashpunk.graphics.interfaces
{
import net.flashpunk.graphics.Anim;

/**
* ...
* @author Ryan Luce
*/
public interface IAnimated
{
function play(name:String = "", reset:Boolean = false):Anim;
}

}


Secondly, you must edit net.flashpunk.graphics.Anim on line 60, changing 
internal var _parent:Spritemap; to
internal var _parent:IAnimated;

making sure you import IAnimated into Anim.as


Whew, if you made it this far, you've got dedication! Enjoy the rewards  Cool

Code:
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.graphics.interfaces.IAnimated;
/**
* ...
* @author Ryan Luce
*/
public class SpritemapRotated extends Image implements IAnimated
{
public var frameAngle:Number = 0;
/**
* If the animation has stopped.
*/
public var complete:Boolean = true;

/**
* Optional callback function for animation end.
*/
public var callback:Function;

/**
* Animation speed factor, alter this to speed up/slow down all animations.
*/
public var rate:Number = 1;

// Rotation information.
/** @private */ private var _source:BitmapData;
/** @private */ private var _width:uint;
/** @private */ private var _frameCount:uint;
/** @private */ private var _last:int = -1;
/** @private */ private var _current:int = -1;

// Spritemap information.
/** @private */ private var _rect:Rectangle;
/** @private */ private var _height:uint;
/** @private */ private var _columns:uint;
/** @private */ private var _rows:uint;
/** @private */ private var _anims:Object = { };
/** @private */ private var _anim:Anim;
/** @private */ private var _index:uint;
/** @private */ private var _frame:uint;
/** @private */ private var _timer:Number = 0;
/** @private */ private var _numAnimationFrames:uint = 0;
/** @private */ private var _currentRow:uint = 0;

// Global information.
/** @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;
private static var _cache:Vector.<BitmapData> = new Vector.<BitmapData>();
private static var _cacheKey:Array = [];

public function SpritemapRotated(source:Class, frameWidth:uint = 0, frameHeight:uint = 0, frameCount:uint = 36)
{
var tempSource:BitmapData = (new source).bitmapData;
var numRows:uint = Math.ceil(tempSource.width / frameWidth) * Math.ceil(tempSource.height / frameHeight);
_numAnimationFrames = numRows;
_rect = new Rectangle(0, 0, frameWidth, frameHeight);
_frameCount = frameCount;
if (_cacheKey[String(source)] == null)
{


_source = new BitmapData(frameCount * frameHeight, numRows * frameHeight, true, 0x00);
_size[source] = Math.ceil(FP.distance(0, 0, frameWidth, frameHeight));

_width = tempSource.width;

for (var a:uint = 0; a < numRows; a++)
{
doRotation(a, tempSource);
}
_cacheKey[String(source)] = _cache.length;
_cache.push(_source);
} else {
trace("using cached");
_source = _cache[_cacheKey[String(source)]];
}


var rectSize:uint = Math.max(_rect.width, _rect.height);
_rect.width = rectSize;
_rect.height = rectSize;

//FP.stage.addChild(new Bitmap(_source));
super(_source, _rect);


}



/**
* Updates the spritemap's buffer.
*/
override public function update():void
{
// get position of the current frame
_rect.x = _rect.width * uint(_frameCount * (frameAngle / 360));
_rect.y = _currentRow * _rect.height;

if (_flipped) _rect.x = (_width - _rect.width) - _rect.x;

// update the buffer
super.update();
}

/** @private Updates the animation and renders the Image. */
override public function render(point:Point, camera:Point):void
{

frameAngle %= 360;
if (frameAngle < 0) frameAngle += 360;
_current = _currentRow * _frameCount + uint(_frameCount * (frameAngle / 360));
if (_last != _current)
{
_last = _current;
_rect.x = _rect.width * _last;
_rect.y = uint(_rect.x / _width) * _rect.height;
_rect.x %= _width;
update();
}
// update the animation
if (_anim && !complete)
{
_timer += (FP.fixed ? _anim._frameRate : _anim._frameRate * FP.elapsed) * rate;
if (_timer >= 1)
{
while (_timer >= 1)
{
_timer --;
_index ++;
if (_index == _anim._frameCount)
{
if (callback != null) callback();
if (_anim._loop) _index = 0;
else
{
_index = _anim._frameCount - 1;
complete = true;
break;
}
}
}
_currentRow = uint(_anim._frames[_index])
_frame =  _currentRow * _frameCount + uint(_frameCount * (frameAngle / 360));

update();
}
}

// render it to the screen
super.render(point, camera);
}

/**
* Add an Animation.
* @param name Name of the animation.
* @param frames Array of frame indices to animate through.
* @param frameRate Animation speed.
* @param loop If the animation should loop.
* @return A new Anim object for the animation.
*/
public function add(name:String, frames:Array, frameRate:Number = 0, loop:Boolean = true):Anim
{
if (_anims[name]) throw new Error("Cannot have multiple animations with the same name");
(_anims[name] = new Anim(name, frames, frameRate, loop))._parent = this;
return _anims[name];
}

/**
* Plays an animation.
* @param name Name of the animation to play.
* @param reset If the animation should force-restart if it is already playing.
* @return Anim object representing the played animation.
*/
public function play(name:String = "", reset:Boolean = false):Anim
{
if (!reset && _anim && _anim._name == name) return _anim;
_anim = _anims[name];
if (!_anim)
{
_frame = uint(_frameCount * (frameAngle / 360));
_currentRow = 0;
_index = 0;
complete = true;
update();
return null;
}
_index = 0;
_timer = 0;
_currentRow = _anim.frames[0];
_frame = _anim._frames[0] * _frameCount + uint(_frameCount * (frameAngle / 360));
complete = false;
update();
return _anim;
}



/**
* Sets the current frame index. When you set this, any
* animations playing will be stopped to force the frame.
*/
public function get frame():uint { return _frame; }
public function set frame(value:uint):void
{
_currentRow = value;
_anim = null;
value = value * _frameCount + uint(_frameCount * (frameAngle / 360));

//value %= _frameCount;
if (_frame == value) return;
_frame = value ;
update();
}

/**
* Current index of the playing animation.
*/
public function get index():uint { return _anim ? _index : 0; }
public function set index(value:uint):void
{
if (!_anim) return;
value %= _anim._frameCount;
if (_index == value) return;
_index = value;
_frame = uint(_anim._frames[_index]);
update();
}

private function doRotation(index:uint, drawFrom:BitmapData):void
{
var rectSize:uint = Math.max(_rect.width, _rect.height);
var width:uint = rectSize * _frameCount,
height:uint = rectSize,
yOffset:uint = index * rectSize;

var tempRect:Rectangle = new Rectangle(0, 0, _rect.width, _rect.height);

tempRect.x = tempRect.width * index;
tempRect.y = uint(tempRect.x / drawFrom.width) * tempRect.height;
tempRect.x %= _width;

var temp:BitmapData = new BitmapData(_rect.width, _rect.height);
temp.copyPixels(drawFrom, tempRect,new Point(0,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 = rectSize / 2,
x:uint = 0,
y:uint = index * rectSize;

while (x < width)
{
m.identity();
m.translate(-ox, -oy);
m.rotate(a);
m.translate(o + x, o + y);
_source.draw(temp, m, null, null, null, smooth);
x += rectSize;
a += aa;


}



}



}

}
Logged
Gornova81
===========
****
Posts: 271



View Profile WWW
« Reply #1 on: July 01, 2010 »

hi !
Do you have a running example of it? Which version of FP is ?
Logged

p0wn
....................
*
Posts: 14


View Profile Email
« Reply #2 on: July 02, 2010 »

I do have it running, you can see my demo here: http://www.ryanluce.com/hbam/

I believe this is fp 1.0. you can email me ryan@santaur.com if you need help getting it working.
Logged
LoveGoblin
--------------

Posts: 1


View Profile
« Reply #3 on: August 31, 2010 »

Hey, thanks a lot for this. I was on the verge of giving up and writing my own when I stumbled across this thread, which would have been a pain given that I'm still new to both FlashPunk and Actionscript.

Just a note: if you want the image to rotate around its center, rather than around the upper-left corner, just do this:

spritemap.centerOrigin();

Where spritemap is your SpritemapRotated object. As I understand it, this is a new method in FlashPunk 1.4.
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC