/*
#=======================#
#== AS3 Sprite Parser ==#
#== Made by zhade ==#
#=======================#
*/
package parser.ragnarok {
import flash.utils.Timer;
import flash.utils.*;
import flash.display.*;
import flash.errors.*;
import flash.events.*;
import flash.geom.*;
import flash.net.*;
public class SpriteParser {
private var SPRBA
:ByteArray =
new ByteArray(); // The .spr file from which we gonna parse the information
private var spriteData
:Array =
new Array(); // This will only store the .spr version, ident and number of frames (PAL & RGB)
private var actData
:Array =
new Array(); // In this array will store almost the entire act data, including each actions, its frames and the subframes information
private var frameData
:Array =
new Array(); // This saves the sprites width, height, data length and offset of the images in the .spr file
private var paletteData
:Array =
new Array(); // Pretty much self-explanory right? Structure is paletteData[index(hex)] = RR:GG:BB
private var soundData
:Array =
new Array(); // Contains the path to sound files in grf, saved as strings
private var bitmapArray
:Array =
new Array(); // Contains the from .spr to Flash Bitmap converted images
private var curAct
:int; // Which action are we currently viewing? Needed for the UI
private var curFrame
:int; // Which frame, also needed for UI
private var frameIdx
:int; // An index used for a loop
private var xDimMin:*, xDimMax:*, yDimMin:*, yDimMax:* = null;
public var mcFrame
:MovieClip =
new MovieClip(); // The movieclip that will hold the frames patterns
private var fileName
:String; // Name of the input string without extension
private var runTimer
:Timer =
new Timer( 0 ); // Every 2/1000 sec a frame is converted from .spr to Bitmap. Is needed to prevent the application freeze
private var playTimer
:Timer =
new Timer( 1000 ); // Timer for the playback, needed for UI. ( Value is changed later in code )
private var useCallback
:Boolean =
false; // Is set to true if user sets a function for callback
private var callback
:Function; // the function the user has set
private var startPoint
:Point =
new Point( 0, 0 ); // default position, where the sprite is being placed
private var useFixedFrames
:Boolean =
false; // This determines whether the frameLoading process is loading all Frames or just specifics.
private var hasParent
:Boolean =
false;
private var hasChilds
:Boolean =
false;
private var parentSpr:SpriteParser = null;
public var isEquipment
:Boolean =
false;
private var finished
:Boolean =
false; // After the parsing process this is set to true
private var partialFinish
:int;
private var FrameTimer
:Number;
// Constructor of the class, either input a string for spr or do it later with the parse() function
public function SpriteParser
( SPRFilename
:String =
null ):void {
if( SPRFilename != null) parse( SPRFilename );
} // End function
// o=====================================================o
// o=====================================================o
// o== ==o
// o== Sprite Parsing ==o
// o== ==o
// o=====================================================o
// o=====================================================o
// Load the file, and call the actual parsing function. If it has been parsed before, show error
public function parse( SPRFilename
:String, useFixed
:Boolean=
false ):void {
useFixedFrames = useFixed;
try {
if( finished
) throw new Error( "Attempting to parse file twice. If you want to parse another sprite please create a new instance." );
fileName = SPRFilename;
if( SPRFilename.lastIndexOf( "." ) != -1 ) fileName = SPRFilename.slice( 0, SPRFilename.lastIndexOf( "." ) );
SPRLoader
.addEventListener( Event.COMPLETE, sprLoaded
);
SPRLoader.load( SPRRequest );
SPRRequest = null;
trace( err );
}
} // End function
// Parse the sprite file. There isn't much I can say, without explaining the .spr file format.
// Read the arrays string indexes, it should give you an idea what its reading at that point.
private function sprLoaded
( ev
:Event ):void {
trace( "Starting Sprite Parsing (SPR)" );
SPRLoader
.removeEventListener( Event.COMPLETE, sprLoaded
);
SPRBA = SPRLoader.data;
SPRBA
.endian =
Endian.LITTLE_ENDIAN;
spriteData['ident'] = SPRBA.readUTFBytes( 2 );
spriteData['version'] = SPRBA.readUnsignedShort().toString( 16 );
spriteData['num_pal'] = SPRBA.readUnsignedShort();
spriteData['num_rgba'] = SPRBA.readUnsignedShort();
for( i = 0; i < spriteData['num_pal']; i++ ) {
frameData[i] = {
width: SPRBA.readUnsignedShort(),
height: SPRBA.readUnsignedShort(),
data_len: SPRBA.readUnsignedShort(),
type: 0,
offset: SPRBA.position
};
SPRBA.position += frameData[i]['data_len'];
//trace( i + ": " + frameData[i]['width'] + " / " + frameData[i]['height'] );
} // End for-loop
for( i = 0; i < spriteData['num_rgba']; i++ ) {
var idx = spriteData['num_pal'] + i;
var Width
:uint = SPRBA
.readUnsignedShort();
var Height
:uint = SPRBA
.readUnsignedShort();
frameData[idx] = {
width: Width,
height: Height,
data_len: Width * Height * 4,
type: 1,
offset: SPRBA.position
};
SPRBA.position += frameData[idx]['data_len'];
//trace( idx + ": " + frameData[idx]['width'] + " / " + frameData[idx]['height'] );
} // End for-loop
// After the frames are done, we are almost at the end of the file.
// The only thing thats left is the color palette. (Note that even if its a sprite with only RGBA
// images, it will still have a palette, or so I hope =P
// The palette is, fortunately, always 1024 bytes long.
// There are 256 colors, saved in RRGGBBAA structure. 256 * 4 = 1024.
spriteData['PAL'] = SPRBA.position;
var IdxColor;
for( var p = 0; p < 256; p++ ) {
paletteData[p.toString( 16 )] = decToCol( SPRBA.readUnsignedByte() << 16 |
SPRBA.readUnsignedByte() << 8 |
SPRBA.readUnsignedByte() );
SPRBA.position += 0x01;
} // End for-loop
/* while( SPRBA.position < SPRBA.length && paletteData.length <= 256 ) {
IdxColor = SPRBA.readUnsignedByte().toString( 16 );
if( b < 256 ) {
if( IdxColor.length < 2 ) IdxColor = "0" + IdxColor;
SColor = SColor + IdxColor + ":";
} // End if
a++;
if( a >= 4 ) {
paletteData[b.toString( 16 )] = SColor.slice( 0, SColor.length - 1 );
SColor = "";
b++;
a = 0;
} // End if
} // End while-loop
*/ trace( "Time: " + (getTimer() - TIME) );
parseAct();
} // End function
private function loadFrames():void {
trace( "Starting Frame Conversion" );
FrameTimer=getTimer();
runTimer
.addEventListener( TimerEvent.TIMER, frameLoading
);
runTimer.start();
} // End function
private function frameLoading
( ev
:TimerEvent ):void {
if(useFixedFrames) frameIdx = fixedFrames[0];
if( frameIdx < ( spriteData['num_pal'] + spriteData['num_rgba'] ) ) {
if( !bitmapArray[frameIdx] ) {
var SPRBitmapData
:BitmapData =
new BitmapData( frameData
[frameIdx
]['width'], frameData
[frameIdx
]['height'], true);
SPRBA.position = frameData[frameIdx]['offset'];
// Is PAL image (Data Structure: [Palette Index, [Length:Optional]])
// The length is only defined for the first index in the palette, meaning 00
if( frameData[frameIdx]['type'] == 0 ) {
var bgx = 0;
var bgy = 0;
var tmpColor;
var fColor;
var tmpLength;
var trans = "ff";
var cidx = 0;
var pixels:Vector.<uint> = new Vector.<uint>(frameData[frameIdx]['width']*frameData[frameIdx]['height'], true);
//for( var i = 0; i < frameData[frameIdx]['data_len']; i++ ) {
while( SPRBA.position < ( frameData[frameIdx]['offset'] + frameData[frameIdx]['data_len'] ) ) {
tmpColor = SPRBA.readUnsignedByte().toString( 16 );
if( tmpColor == 00 ) {
trans = "00";
tmpLength = SPRBA.readUnsignedByte();
} else {
tmpLength = 1;
trans = "ff";
} // End if
for( var c = 0; c < tmpLength; c++ ) {
// fColor = paletteData[tmpColor].split( ":" );
// fColor = int( "0x" + trans + fColor[0] + fColor[1] + fColor[2] );
fColor = "0x" + trans + paletteData[tmpColor];
//--SPRBitmapData.setPixel32( bgx, bgy, fColor );
pixels[cidx] = fColor;
cidx++;
bgx++;
if( bgx >= frameData[frameIdx]['width'] ) {
bgx = 0;
bgy++;
} // End if
} // End for-loop
} // End while-loop
SPRBitmapData.setVector( SPRBitmapData.rect, pixels );
// Is RGBA image (Data Structure: [AABBGGRR], It also goes from top to bottom unlike the PAL image.)
} else if( frameData[frameIdx]['type'] == 1 ) {
var bgx2 = 0;
var bgy2 = frameData[frameIdx]['height'] - 1;
//var rColor:Array = new Array();
var rColor;
while( SPRBA.position < ( frameData[frameIdx]['offset'] + frameData[frameIdx]['data_len'] ) ) {
rColor = "0x" + toRGB( SPRBA.readUnsignedByte() << 24 |
SPRBA.readUnsignedByte() |
SPRBA.readUnsignedByte() << 8 |
SPRBA.readUnsignedByte() << 16 );
/* rColor = [
SPRBA.readUnsignedByte().toString( 16 ),
SPRBA.readUnsignedByte().toString( 16 ),
SPRBA.readUnsignedByte().toString( 16 ),
SPRBA.readUnsignedByte().toString( 16 )
];
if( rColor[0].length < 2 ) rColor[0] = "0" + rColor[0];
if( rColor[1].length < 2 ) rColor[1] = "0" + rColor[1];
if( rColor[2].length < 2 ) rColor[2] = "0" + rColor[2];
if( rColor[3].length < 2 ) rColor[3] = "0" + rColor[3];
SPRBitmapData.setPixel32( bgx2, bgy2, int( "0x" + rColor[0] + rColor[3] + rColor[2] + rColor[1] ) );
*/
SPRBitmapData.setPixel32( bgx2, bgy2, rColor );
bgx2++;
if( bgx2 >= frameData[frameIdx]['width'] ) {
bgx2 = 0;
bgy2--;
} // End if
} // End while-loop
} // End if
bitmapArray[frameIdx] = SPRBitmap;
} // End if
} else {
if(!useFixedFrames) {
runTimer.stop();
runTimer
.removeEventListener( TimerEvent.TIMER, frameLoading
);
// parseAct();
parseComplete();
}
} // End if
if(!useFixedFrames) frameIdx++;
else {
fixedFrames.splice(0,0); // Remove first entry that has been loaded
fixedFrames = reOrderArray(fixedFrames); // Makes all entries move one down, so that the first entry is set again
frameIdx = fixedFrames[0];
if(fixedFrames.length <= 0) {
runTimer.stop();
runTimer
.removeEventListener( TimerEvent.TIMER, frameLoading
);
// parseAct();
parseComplete();
}
} // End if
} // End function
// o=====================================================o
// o=====================================================o
// o== ==o
// o== Act Parsing ==o
// o== ==o
// o=====================================================o
// o=====================================================o
private function parseAct():void {
try {
ACTLoader
.addEventListener( Event.COMPLETE, actLoaded
);
ACTLoader.load( ACTRequest );
ACTRequest = null;
trace( err );
}
} // End function
private function actLoaded
( ev
:Event ):void {
trace( "Starting Sprite Parsing (ACT)" );
ACTLoader
.removeEventListener( Event.COMPLETE, actLoaded
);
ACTBA = ACTLoader.data;
ACTBA
.endian =
Endian.LITTLE_ENDIAN;
actData['ident'] = ACTBA.readUTFBytes( 2 );
actData['version'] = ACTBA.readUnsignedShort().toString( 16 );
actData['num_frames'] = ACTBA.readUnsignedShort();
actData
['num_actions'] =
Math.floor( actData
['num_frames'] / 8 );
ACTBA.position += 0xA; // Those are useless/unused/unknown bytes that we skip
// Loop through the actions
for( anim = 0; anim < actData['num_frames']; anim++ ) {
actData
[anim
] =
new Array();
actData[anim]['num_frames'] = ACTBA.readInt();
// Loop through the actions frames
for( nf = 0; nf < actData[anim]['num_frames']; nf++ ) {
ACTBA.position += 0x20; // Skipped bytes again
actData
[anim
][nf
] =
new Array();
actData[anim][nf]['num_subframes'] = ACTBA.readInt();
// Loop through the frames patterns
for( pat = 0; pat < actData[anim][nf]['num_subframes']; pat++ ) {
actData
[anim
][nf
][pat
] =
new Array();
actData[anim][nf][pat] = {
xOffset: ACTBA.readInt(),
yOffset: ACTBA.readInt(),
sprNo: ACTBA.readInt(),
mirror: ACTBA.readInt(),
red: ACTBA.readUnsignedByte(),
green: ACTBA.readUnsignedByte(),
blue: ACTBA.readUnsignedByte(),
alpha: ACTBA.readUnsignedByte(),
offset: ACTBA.position
};
// There are differences depending on the version
if( actData['version'] >= 200 && actData['version'] <= 203 ) actData[anim][nf][pat]['xyScale'] = ACTBA.readFloat();
if( actData['version'] >= 204 ) {
actData[anim][nf][pat]['xScale'] = ACTBA.readFloat();
actData[anim][nf][pat]['yScale'] = ACTBA.readFloat();
} // End if
actData[anim][nf][pat]['rotation'] = ACTBA.readInt();
actData[anim][nf][pat]['sprType'] = ACTBA.readInt();
if( actData['version'] >= 205 ) {
actData[anim][nf][pat]['sprWidth'] = ACTBA.readInt();
actData[anim][nf][pat]['sprHeight'] = ACTBA.readInt();
} // End if
} // End for-loop
// After the patterns follows the sounds, those are pointers to the sounddata at the end of the actfile.
actData[anim][nf]['soundNo'] = ACTBA.readInt();
var extrainfo = ACTBA.readInt(); // if this is actually 1 in an act, it will give us the info for reference (eg. head/body/headgear)
if( extrainfo == 1 ) {
ACTBA.position += 0x04;
actData[anim][nf]['refX'] = ACTBA.readInt();
actData[anim][nf]['refY'] = ACTBA.readInt();
ACTBA.position += 0x04;
} // End if
} // End for-loop
} // End for-loop
// At the end of the act file we find the sound and interval list
// the sounds are frames specific
soundData['num_sounds'] = ACTBA.readInt();
if( soundData['num_sounds'] > 0 ) {
for( var sn = 0; sn < soundData['num_sounds']; sn++ ) {
soundData[sn] = ACTBA.readUTFBytes(40);
} // End for-loop
} // End if
// the intervals are actions specific
for( var intv = 0; intv < actData['num_frames']; intv++ ) {
actData[intv]['interval'] = ACTBA.readFloat();
} // End if
trace( "Time: " + (getTimer() - TIME) );
// parseComplete();
if(useFixedFrames) displayFirstFrame();
else loadFrames();
} // End function
// Clean up to reduce memory usage?
private function parseComplete():void {
SPRLoader.close();
ACTLoader.close();
SPRLoader = null;
ACTLoader = null;
SPRBA = null;
ACTBA = null;
runTimer = null;
mcCapture.graphics.beginFill(0xFFFFFF,0.15);
mcCapture.graphics.drawRect( -1, -1, mcCapture.width+1, mcCapture.height+1 );
mcCapture.graphics.endFill();
trace( "Time: " + (getTimer() - FrameTimer) );
finished = true;
if( hasParent ) parentSpr.partFinish();
else partFinish();
/*if( useFixedFrames ) displayAction(0, 0);
if( useCallback ) callback(this);*/
} // End function
// o=====================================================o
// o=====================================================o
// o== ==o
// o== Functions ==o
// o== ==o
// o=====================================================o
// o=====================================================o
// Eh ya, put our info from the actData together and display it on stage I guess...
// We loop through each pattern of the specific frame and do some magic to it and then display it.
public function displayAction
( action
:int =
0, frame:int =
0 ):void {
if( hasChilds ) {
for( var i = 0; i < childArray.length; i++ ) {
childArray[i].displayAction( action, frame );
} // End for-loop
}
try {
if( !finished
) throw new Error( "Cannot display action when sprite is not fully parsed" );
if( action != curAct ) {
xDimMin = null;
xDimMax = null;
yDimMin = null;
yDimMax = null;
} // End if
curAct = action;
curFrame = frame;
var numPattern
:int = actData
[action
][frame]['num_subframes'];
while ( mcFrame.numChildren > 0 ) {
delete( mcFrame.getChildAt( 0 ) );
mcFrame.removeChildAt( 0 );
} // End while-loop
if( !animCache
[curAct
] ) animCache
[curAct
] =
new Array();
for( var pat = 0; pat < numPattern; pat++ ) {
var patData = actData[action][frame][pat];
if( patData['sprNo'] >= 0 ) {
var frameNumPadding = ( patData['sprType'] == 1 ) ? spriteData['num_pal'] : 0;
var tempBitmapData
:BitmapData = bitmapArray
[patData
['sprNo'] + frameNumPadding
].bitmapData.clone();
patLayer.ID = pat;
patLayer.addChild( tempBitmap );
mcFrame.addChild( patLayer );
var Alpha
:Number = patData
['alpha'] / 255;
var Red
:Number = patData
['red'] / 255;
var Green
:Number = patData
['green'] / 255;
var Blue
:Number = patData
['blue'] / 255;
cTrans.alphaMultiplier = Alpha;
cTrans.redMultiplier = Red;
cTrans.greenMultiplier = Green;
cTrans.blueMultiplier = Blue;
patLayer.transform.colorTransform = cTrans;
var Mirror = 1;
if( patData['mirror'] == 1 ) Mirror = -1;
var xScale = 1;
var yScale = 1;
if( actData['version'] >= 200 && actData['version'] <= 203 ) {
xScale = patData['xyScale'];
yScale = patData['xyScale'];
} else {
xScale = patData['xScale'];
yScale = patData['yScale'];
} // End if
patLayer.scaleX *= xScale * Mirror;
patLayer.scaleY *= yScale;
if( hasParent ) {
var newOffsetX = null;
var newOffsetY = null;
// if( !isEquipment ) {
var refOffset
:Array = parentSpr
.getRefOffset
( curAct
, curFrame
);
newOffsetX = patData['xOffset'] + refOffset[0] - actData[curAct][curFrame]['refX'];
newOffsetY = patData['yOffset'] + refOffset[1] - actData[curAct][curFrame]['refY'];
// } else {
// newOffsetX = patData['xOffset'] - actData[curAct][curFrame]['refX'];
// newOffsetY = patData['yOffset'] - actData[curAct][curFrame]['refY'];
// } // End if
patLayer
.x =
Math.floor( ( startPoint
.x - patLayer
.width / 2 * Mirror
) ) + Math.floor( newOffsetX
);
patLayer
.y =
Math.floor( ( startPoint
.y - patLayer
.height / 2 ) ) + Math.floor( newOffsetY
);
} else {
patLayer
.x =
Math.floor( ( startPoint
.x - patLayer
.width / 2 * Mirror
) ) + Math.floor( patData
['xOffset'] );
patLayer
.y =
Math.floor( ( startPoint
.y - patLayer
.height / 2 ) ) + Math.floor( patData
['yOffset'] );
} // End if
if( Math.round( patData
['rotation'] ) !=
0 ) {
var ptRotationPoint
:Point =
new Point( Math.floor( patLayer
.x + patLayer
.width / 2 * Mirror
), Math.floor( patLayer
.y + patLayer
.height / 2 ) );
rotateAroundCenter( patLayer, patData['rotation'], ptRotationPoint);
} // End if
} else {
mcFrame
.addChild( new MovieClip() ); // useless
} // End if
} // End for-loop
if( count( animCache[curAct] ) < actData[curAct]['num_frames'] ) {
if( mcFrame.numChildren > 0 ) {
if( xDimMin == null ) xDimMin = mcFrame.getBounds( mcFrame ).x;
if( xDimMax == null ) xDimMax = mcFrame.getBounds( mcFrame ).x + mcFrame.width;
if( yDimMin == null ) yDimMin = mcFrame.getBounds( mcFrame ).y;
if( yDimMax == null ) yDimMax = mcFrame.getBounds( mcFrame ).y + mcFrame.height;
if( xDimMin > mcFrame.getBounds( mcFrame ).x ) xDimMin = mcFrame.getBounds( mcFrame ).x;
if( xDimMax < mcFrame.getBounds( mcFrame ).x + mcFrame.width ) xDimMax = mcFrame.getBounds( mcFrame ).x + mcFrame.width;
if( yDimMin > mcFrame.getBounds( mcFrame ).y ) yDimMin = mcFrame.getBounds( mcFrame ).y;
if( yDimMax < mcFrame.getBounds( mcFrame ).y + mcFrame.height ) yDimMax = mcFrame.getBounds( mcFrame ).y + mcFrame.height;
} // End if
animCache[curAct][curFrame] = 1;
} else {
if( !dimArray
[curAct
] ) dimArray
[curAct
] =
new Matrix( xDimMin
, yDimMin
, ( xDimMax
- xDimMin
), ( yDimMax
- yDimMin
) );
mcCapture.width = dimArray[curAct].c;
mcCapture.height = dimArray[curAct].d;
mcCapture.x = dimArray[curAct].a + mcCapture.width;
mcCapture.y = dimArray[curAct].b + mcCapture.height;
} // End if
// var tmpMatrix:Matrix = new Matrix();
// tmpMatrix.translate( -mcFrame.getBounds(mcFrame).x, -mcFrame.getBounds(mcFrame).y );
// var cacheBitmapData:BitmapData = new BitmapData( mcFrame.width, mcFrame.height, true, 0x00000000 );
// var cacheBitmap:Bitmap = new Bitmap( cacheBitmapData );
// cacheBitmapData.draw( mcFrame, tmpMatrix );
// animCache[curAct][curFrame] = cacheBitmap;
// } // End if
trace( err );
}
} // End function
private function rotateAroundCenter
( ob
:*, angleDegrees
:Number, ptRotationPoint
:Point ):void {
var m
:Matrix = ob
.transform.matrix;
m.tx -= ptRotationPoint.x;
m.ty -= ptRotationPoint.y;
m
.rotate( angleDegrees
* ( Math.PI / 180 ) );
m.tx += ptRotationPoint.x;
m.ty += ptRotationPoint.y;
ob.transform.matrix = m;
}
private function startAnimation
( ev
:TimerEvent ):void {
curFrame++;
if( curFrame >= actData[curAct]['num_frames'] ) curFrame = 0;
gotoFrame( curFrame );
if( hasChilds ) {
for( var i = 0; i < childArray.length; i++ ) {
childArray[i].gotoFrame( curFrame );
} // End for-loop
} // End if
} // End function
var red, green, blue;
blue = ( dec & 255 ).toString( 16 );
green = ( ( dec & 65280 ) / 256 ).toString( 16 );
red = ( ( dec & 16711680) / 65536 ).toString( 16 );
red = ( red.length < 2 ) ? "0" + red : red;
green = ( green.length < 2 ) ? "0" + green : green;
blue = ( blue.length < 2 ) ? "0" + blue : blue;
return ( red + green + blue );
} // End function
return dec.toString( 16 );
} // End function
private function count
( arr
:Array ):int {
for( var i = 0; i < arr.length; i++ ) {
if( arr[i] != null ) count++;
}
return count;
} // End function
private function getRefOffset
( action
:int, frame:int ):Array {
return new Array( actData
[action
][frame]['refX'], actData
[action
][frame]['refY'] );
} // End function
private function setChild( sprite:SpriteParser ):void {
hasChilds = true;
childArray.push( sprite );
} // End function
private function reOrderArray
( arr
:Array ):Array {
for( var i=0; i<arr.length; i++ ) {
if( (i+1) <= arr.length && arr[i+1] != null) {
newArr[i] = arr[i+1];
}
} // End for-loop
return newArr;
} // End function
private function displayFirstFrame():void {
fixedFrames =
new Array();
// Get required frames from patterns
var PatCount = actData[0][0]['num_subframes'];
for( var i = 0; i < PatCount; i++ ) {
//trace("Pat: "+i+" SprNo: "+actData[0][0][i]['sprNo']);
if(actData[0][0][i]['type'] == 1) fixedFrames.push(actData[0][0][i]['sprNo']+spriteData['num_pal']);
else fixedFrames.push(actData[0][0][i]['sprNo']);
} // End for-loop
loadFrames();
} // End function
public function partFinish():void {
partialFinish++;
if( hasChilds || hasParent ) {
if( partialFinish >= ( count( childArray ) + 1 ) ) {
mcFrame.visible = true;
if( useFixedFrames ) displayAction(0, 0);
if( useCallback ) callback(this);
} // End if
} else {
mcFrame.visible = true;
if( useFixedFrames ) displayAction(0, 0);
if( useCallback ) callback(this);
} // End if
} // End function
// o=====================================================o
// o=====================================================o
// o== ==o
// o== Public Functions ==o
// o== ==o
// o=====================================================o
// o=====================================================o
public function isLoaded
( func
:Function ):void {
useCallback = true;
callback = func;
} // End function
public function setPosition
( xPos
:int, yPos
:int ):void {
startPoint.x = xPos;
startPoint.y = yPos;
if( mcFrame.numChildren > 0 && finished ) {
for( var pat = 0; pat < mcFrame.numChildren; pat++ ) {
var patLayer = mcFrame.getChildAt( pat );
var patData = actData[curAct][curFrame][patLayer.ID];
var Mirror = 1;
if( patData['mirror'] == 1 ) Mirror = -1;
patLayer
.x =
Math.floor( ( startPoint
.x - patLayer
.width / 2 * Mirror
) ) + Math.floor( patData
['xOffset'] );
patLayer
.y =
Math.floor( ( startPoint
.y - patLayer
.height / 2 ) ) + Math.floor( patData
['yOffset'] );
} // End for-loop
} // End if
} // End function
public function setFrame
( mc
:MovieClip ):void {
mcFrame = mc;
} // End function
public function gotoFrame
( frame:int =
0 ):void {
if( frame >= 0 && frame < actData[curAct]['num_frames'] ) {
displayAction( curAct, frame );
} // End if
} // End function
public function nextFrame():void {
if( ( curFrame + 1 ) < actData[curAct]['num_frames'] ) displayAction( curAct, ( curFrame + 1 ) );
else displayAction( curAct, 0 );
} // End function
public function prevFrame():void {
if( ( curFrame - 1 ) >= 0 ) displayAction( curAct, ( curFrame - 1 ) );
else displayAction( curAct, ( actData[curAct]['num_frames'] - 1 ) );
} // End function
public function playStopAnimation():void {
if( !hasParent ) {
if( !playTimer.running ) {
playTimer.stop();
playTimer.delay = 22 * actData[curAct]['interval'];
playTimer
.addEventListener( TimerEvent.TIMER, startAnimation
);
playTimer.start();
} else {
playTimer.stop();
} // End if
} // End if
} // End function
public function nextAct():void {
if( ( curAct + 1 ) < actData['num_frames'] ) displayAction( ( curAct + 1 ), 0 );
else displayAction( 0, 0 );
} // End function
public function prevAct():void {
if( ( curAct - 1 ) >= 0 ) displayAction( ( curAct - 1 ), 0 );
else displayAction( ( actData['num_frames'] - 1 ), 0 )
} // End function
public function generatePalette
():Bitmap {
try {
if( !finished
) throw new Error("Cannot generate palette when sprite is not fully parsed");
var pColor = 0;
var X=0;
var Y=0;
for( var i = 0; i < 256; i++ ) {
pColor = "0x" + paletteData[i.toString( 16 )];
paletteBitmapData
.fillRect( new Rectangle( X
* 16, Y
* 16, 16, 16 ), pColor
);
X++;
if( X >= 16 ) {
X = 0;
Y++;
}
}
trace( err );
}
return paletteBitmap;
} // End function
public function setParent( sprite:SpriteParser ):void {
hasParent = true;
parentSpr = sprite;
sprite.setChild( this );
} // End function
public function getCurFrame
():int {
return curFrame;
} // End function
public function getFrameCount
():int {
return actData[curAct]['num_frames'];
} // End function
public function getCurAct
():int {
return curAct;
} // End function
public function getActCount
():int {
return actData['num_frames'];
} // End function
} // End class
} // End package