In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Touch Event를 이용한 비행기 컨트롤 (Android)

터치 이벤트를 이용해 비행기를 컨트롤해보자. +표시 를 중심으로 터치해보세요. 그 방향으로 비행기가 움직입니다. +에서 터치포인트가 멀어지면 속도도 증가합니다.
Get Adobe Flash player
by jidolstar 08 Jan 2011
/**
 * Copyright jidolstar ( http://wonderfl.net/user/jidolstar )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/4Akd
 */

// forked : keyboard Test 
// arrows or [wad] to move,rotation
//--------------------------------------------------------------------------------
package {
    import flash.display.*;
    import flash.events.*;
    import flash.filters.*;
    import flash.geom.*;
    import flash.ui.*;
    import flash.utils.*;
    
    import net.hires.debug.Stats;
    
    [SWF(backgroundColor='#000000', frameRate='30')]
    
    /**
     * Touch Event를 이용한 비행기 컨트롤 (Android)
     * @author jidolstar
     * @see http://blog.jidolstar.com/672
     */
    public class MobileShootGame extends Sprite {
        
        function MobileShootGame() {
            if (stage) {
                ADDED_TO_STAGE();
            } else {
                addEventListener(Event.ADDED_TO_STAGE, ADDED_TO_STAGE);
            }
        }
        
        
        private function ADDED_TO_STAGE($e:Event=null):void {
            // stage
            stage.tabChildren=false;
            stage.stageFocusRect=false;
            stage.mouseChildren=false;
            stage.align=StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            //stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
            
            
            WIDTH = stage.stageWidth;
            HEIGHT = stage.stageHeight;
            
            _landscape = new Landscape(WIDTH, HEIGHT);
            _screen = new BitmapData(WIDTH, HEIGHT, true, 0x0);
            
            // background
            addChild(_landscape);
            
            // rendering layer 
            addChild(new Bitmap(_screen));
            
            // initialize
            _plane=new Plane(_screen.width >> 1, _screen.height >> 1, 0);
            
            // event listener
            stage.addEventListener(Event.ENTER_FRAME, ENTER_FRAME);
            
            // Stats
            var stats:Stats;
            addChild(stats = new Stats);
            stats.alpha = 0.5;
            

            TOUCH_SETUP();
        }
        
        
        private function TOUCH_SETUP():void {
            
            //조정위치 및 영역 
            MoveControl.controlXCenter = stage.stageWidth/2;
            MoveControl.controlYCenter = stage.stageHeight-100;
            MoveControl.controlCenterRadius = 50;
            
            var speedBox:Sprite = new Sprite();
            speedBox.graphics.clear();
            speedBox.graphics.lineStyle(1,0xff000,1.0);
            speedBox.graphics.moveTo(MoveControl.controlXCenter, MoveControl.controlYCenter-50);
            speedBox.graphics.lineTo(MoveControl.controlXCenter, MoveControl.controlYCenter+50);
            speedBox.graphics.moveTo(MoveControl.controlXCenter-50, MoveControl.controlYCenter);
            speedBox.graphics.lineTo(MoveControl.controlXCenter+50, MoveControl.controlYCenter);
            addChild(speedBox);

            var dots:Object = new Object();
            var dotCount:uint = 0;
            var THIS:DisplayObjectContainer = stage;
            if(Multitouch.supportsTouchEvents) {
                Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
                stage.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
                stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
                stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd);
                
                function onTouchBegin(e:TouchEvent):void {
                    if (dotCount == 1/*Multitouch.maxTouchPoints*/) return;
                    var dot:Sprite = getCircle();
                    dot.x = e.stageX;
                    dot.y = e.stageY;
                    THIS.addChild(dot);
                    ++dotCount;
                    dots[e.touchPointID] = dot;
                    MoveControl.calc(e.stageX, e.stageY);
                    //dot.startTouchDrag(e.touchPointID, true);
                }
                function onTouchMove(e:TouchEvent):void {
                    var dot:Sprite = dots[e.touchPointID];
                    dot.x = e.stageX;
                    dot.y = e.stageY;
                    MoveControl.calc(e.stageX, e.stageY);
                }
                function onTouchEnd(e:TouchEvent):void {
                    var dot:Sprite = dots[e.touchPointID];
                    THIS.removeChild(dot);
                    delete dots[e.touchPointID];
                    --dotCount;
                    MoveControl.clear();
                }
            } else {
                stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
                
                function onMouseDown(e:MouseEvent):void {
                    var dot:Sprite = getCircle();
                    dot.x = e.stageX;
                    dot.y = e.stageY;
                    THIS.addChild(dot);
                    dots[0] = dot;
                    MoveControl.calc(e.stageX, e.stageY);
                    stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
                    stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
                    //dot.startTouchDrag(e.touchPointID, true);
                }
                function onMouseMove(e:MouseEvent):void {
                    var dot:Sprite = dots[0];
                    dot.x = e.stageX;
                    dot.y = e.stageY;
                    MoveControl.calc(e.stageX, e.stageY);
                }
                function onMouseUp(e:MouseEvent):void {
                    var dot:Sprite = dots[0];
                    THIS.removeChild(dot);
                    delete dots[0];
                    MoveControl.clear();
                    stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
                    stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
                }
            }
            
            function getCircle(circumference:uint = 20):Sprite {
                var circle:Sprite = new Sprite();
                circle.graphics.beginFill((dotCount==0)?0x1695A3:0xff0000);
                circle.graphics.drawCircle(0, 0, circumference);
                return circle;
            }
        }
        

        
        private function ENTER_FRAME($e:Event):void {
            //update
            _plane.update();
            
            //rendering
            _screen.lock();
            _screen.colorTransform(_screen.rect,new ColorTransform(1,1,1,0.9,0,0,0));
            _screen.fillRect(_screen.rect, 0x000000);
            _plane.render();
            _screen.unlock();
        }
    }
}

import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.system.*;
import flash.ui.*;
import flash.utils.*;

var _plane:Plane;
var _landscape:Landscape;
var _screen:BitmapData;
var _mainScreen:Sprite;
var WIDTH:Number;
var HEIGHT:Number;

class MoveControl {
    static public var controlXCenter:Number;
    static public var controlYCenter:Number;
    static public var controlCenterRadius:Number;
    static public var speed:Number = 0;
    static public var planeDirection:Number = 0;
    static public var direction:Number = 0;
    
    static public function calc($x:Number, $y:Number):void {
        var dx:Number = controlXCenter - $x;
        var dy:Number = controlYCenter - $y;
        
        speed = Math.sqrt(dx*dx+dy*dy);
        if(speed > 100) speed = 100;
        speed /= 10;
        
        direction = Math.atan2(dy, dx)*180/Math.PI;
    }
    
    static public function clear():void {
        //left = 0;
        //right = 0;
        //up = 0;
        speed = 0;
        
    }
}


// Resource
//----------------------------------------------------------------------------------------------------
class DisplayImage {
    public var bmp:BitmapData;
    public var rect:Rectangle;
    public var cx:int, cy:int;
    
    function DisplayImage($bmp:BitmapData, $cx:int, $cy:int) {
        bmp=$bmp;
        cx=$cx;
        cy=$cy;
        trimming();
    }
    
    private function trimming():void {
        var r:Rectangle=bmp.getColorBoundsRect(0xFF000000, 0x00000000);
        var temp:BitmapData=new BitmapData(r.width, r.height, true, 0x00000000);
        cx-=r.x;
        cy-=r.y;
        temp.copyPixels(bmp, r, new Point(0, 0));
        bmp.dispose();
        bmp=temp;
        rect=r;
    }
}

// Plane
//----------------------------------------------------------------------------------------------------
class Plane {
    private const D2R:Number=Math.PI / 180; //Degree -> Radian
    private const ROT_STEPS:Number=100;
    private const ROT_STEP_DIRECTION:Number=ROT_STEPS / 360;
    private const FRAMES:int=3;
    private const KEY_W:int=87;
    private const KEY_D:int=68;
    private const KEY_A:int=65;
    private const KEY_UP:int=Keyboard.UP;
    private const KEY_RIGHT:int=Keyboard.RIGHT;
    private const KEY_LEFT:int=Keyboard.LEFT;
    private var loader:Loader=new Loader();
    private var rotArr:Vector.<DisplayImage>=new Vector.<DisplayImage>(3 * ROT_STEPS, true);
    private var r:Number=-90; //rotation
    private var vr:Number=0; //rotation velocity
    private var x:Number=0; //x-axis position
    private var y:Number=0; //y-axis position
    private var v:Number=0;
    private var currentImg:DisplayImage;
    private var currentFrame:int=0;
    private var frameInterval:Number=0;
    private var ready:int=0;
    private var planeBitmap:Bitmap;
    
    
    function Plane($x:Number, $y:Number, $rotation:Number) {
        // 원본이미지를 Base64로 Encode 하는 방법 
        //[Embed(source="../assets/brownplane.png")]
        //private var PLANE:Class;
        //var plane:Bitmap = new PLANE as Bitmap;
        //var encoder:Base64Encoder = new Base64Encoder;
        //var byte:ByteArray = (new PNGEncoder).encode(plane.bitmapData);
        //encoder.encodeBytes( byte );
        //trace( encoder.drain() );
        
        // plane base64 data 
        // http://www.brighthub.com/internet/web-development/articles/11010.aspx
        // plane image : http://www.brighthub.com/internet/web-development/articles/11010.aspx
        var pdata:String="", byteArr:ByteArray;//, base64Dec:Base64Decoder=new Base64Decoder();
        pdata+="iVBORw0KGgoAAAANSUhEUgAAAMMAAABBCAYAAABsBxB5AAAF5UlEQVR42u2dr1fcWBiGx1UgViAq";
        pdata+="KhCIFRUViAoEAoGsQFZUjFgxYkUFArECMaJ/AKKiogKBWIkYUYlArEAgVyAqkZVZ3tt9c765JJmE";
        pdata+="mUBO53nP+U6SmztfvvuU5N7cH+lohBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIoV9Pm3uTYmdnpzQd";
        pdata+="wwAGa8fgxet3xV8Hr4q/j3eLq8+HaatjpcMABuvEYLS//aKYfToobmeT4u7qKG11rHQYwGBtGKga";
        pdata+="1N2vJ4EA/Li9TlsdK30dqkkY/MIMilwbvyU7OjqaM+Xd2HlffJ3sFDfnH4ri32mCoK2Ola7zXX0O";
        pdata+="QXlcjjdXFwZdfA6ZwTJ/B118Dkq/b45SQXR3y7SvtLydqHRViRGCjpWetxfb+IQBDAZX7TlYFUjm";
        pdata+="oGOVt7W1NQfBZgg639UnDGAwLG3vpd4ABRrvcqXpXA5BhRm9PSjNhYsQ2vqEAQyeRC8PjtPdJ1M7";
        pdata+="TtWXTMHaVF19Otwu79wYsNL+eLuZ8si0r8Kq4F9ubovrH0Xa6ljped46n64mYxyOTXE6ZsUPAxg8";
        pdata+="moHbc+rmchutyZQvVmN5wAbkfeV99/l87iVQx0rP8zZB6Bpfl/5rGMCgBBAvbnO7Lj9Wl9giCG7r";
        pdata+="GcL4fJaeBjYdG0LM2wRB15XFNmeMzefjb9qAgAEM0ouKLuw77e7mWxmQ7PvleUrTNqbLNJReF7DO";
        pdata+="VUG4+H5XWhWEtj7bxOcng/w3vXTBAAbl0yBCiHZzMS2urq6K6eV12qbjcP7k5KQMOL8TfS6vHj9e";
        pdata+="XJZWVT229dkmvgih6akAAxjMzRVxOyzaP1+PU7Cj0be01XE8v+juzSFsTY5TwW06ziEs8tklPrcX";
        pdata+="F819gQEMyupRb+4OVKbuK9l0Oi3Ozs7SBWazWXF5OnlwAQcc+4xdcOezb+2r4Db7yPPW+cz/oVI8";
        pdata+="93EpPsWpeB27yyJ/Kt+iJgIMYFA+Fd6/2Sg+7r2cgyHTsPfp6encBeKF6qqyKgiurmwuWB2Eqpeg";
        pdata+="PAbFpfgUZ4xbflQelavtyyMMYFCC0MxB/ejP3c1UpeRA8iAiBAUjixCcz340B8U9ANp6Tkqet85n";
        pdata+="1fXzgituxa9yqDxduxVhAIOyqtTonn6cA8kvaPMLjRdq+OWmCYJnKzZBqPJZF0Ne8DQd+L4cjxm2";
        pdata+="hwEMHow8aiRPI3u7r0YlEJkuePrhdTJDGI/HZcDar4NQNXW3DkKVT+X1tRWHY1J8HoVU3KsafYUB";
        pdata+="DFoDUTBNEGK1lbcrY5WX522CEAuueJa+82EAg2WAeH6KgtFdnFdl8SkQC6kXI89l1zb2IsS8dT51";
        pdata+="vV7vfBjA4LGKsxAVaGzTqfr6Mn6TzIX0ulebX3503nndLq3yOTercSCCAQxGceWS17R6PaurMRUu";
        pdata+="WgQRAUTT7+p8eiUUDGAwuJtB1ZMDdl+wA/ZU3DglN4KIAyF53jqfg6gOYQCDOqlKU6E8ZK59pVX1";
        pdata+="X0cQBlDV/9vWJwxgMCgdHv5sx3nIXPtKa+q/ttW9/XfxCQMYDA6Cq7JVBNyHTxjAoHft7+8/CFhp";
        pdata+="Q/MJAxj0Li8KiQs4lh386MMnDGDwJD0JecDLvu334RMGMHgS+UsG/hrCUH3CAAa9SwMkDlj7Q/UJ";
        pdata+="Axj0Lg2QeFHGqj7/14dPGMCgl5elNCS+vVd+SEpzSWT5KOIyFn2m+Sj31/NHomAAg2dloItruq5G";
        pdata+="An23ehah9jU66Lko+YLsrtbkU9dUHM8BAwYw+Kn/v3+pQOLCDAXpEUIH7IlY7gmIy/zqtvE7N1U+";
        pdata+="7c8gnuW7ozCAQQ4hD9iDIk0QFtkin/EbOEP4Q4DBGjOIEOJ8dL/xV0GIINpYk8+h/SHAYI0ZNLUV";
        pdata+="qyDknwNp85HY2FbMfQ69vQyD9WGQpKm2CsArkrTvZX9elKGtF2zHvE0W89tP7jPmfc7/HRIGMChV";
        pdata+="tQbW3V/aX0V3Wu5zaGteYQCD2qeEv1awqju1D58wgMGTtSNX3XbrwycMYIAQQgghhBBCCCGEEEII";
        pdata+="IYQQWqH+A2OxL7+zKnbXAAAAAElFTkSuQmCC";
        // decode
        byteArr=Base64.decode(pdata);
        
        // load
        loader.loadBytes(byteArr, new LoaderContext(false, ApplicationDomain.currentDomain, null));
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, COMPLETE);
        
        //initialize
        x=$x;
        y=$y;
        r=$rotation;
    }
    
    private function COMPLETE($e:Event):void {
        loader=null;
        var i:int, j:int, k:int, src:BitmapData, temp:BitmapData;
        var rect:Rectangle, destPoint:Point, frameWidth:Number, frameHeight:Number, matrix:Matrix;
        var stepBmpList:Vector.<Bitmap>;
        
        src=Bitmap(LoaderInfo($e.target).content).bitmapData
        destPoint=new Point(0, 0);
        frameWidth=src.width / FRAMES;
        frameHeight=src.height;
        
        j=FRAMES;
        stepBmpList=new Vector.<Bitmap>(FRAMES, true);
        while (j--) {
            rect=new Rectangle(j * frameWidth, 0, frameWidth, frameHeight);
            temp=new BitmapData(frameWidth, frameHeight, true, 0x0);
            temp.copyPixels(src, rect, destPoint);
            stepBmpList[j]=new Bitmap(temp);
        }
        
        j=FRAMES;
        matrix=new Matrix;
        rect=new Rectangle(frameWidth, 0, frameWidth, frameHeight);
        while (j--) { //frame 
            i=ROT_STEPS;
            k=j * ROT_STEPS;
            while (i--) { //rotation
                matrix.identity();
                matrix.translate(-frameWidth / 2, -frameHeight / 2);
                matrix.rotate((360 / ROT_STEPS * i) * D2R);
                matrix.translate(frameWidth / 2, frameHeight / 2);
                temp=new BitmapData(frameWidth, frameHeight, true, 0x0);
                temp.draw(stepBmpList[j], matrix, null, null, null, true);
                rotArr[i + k]=new DisplayImage(temp, frameWidth / 2, frameHeight / 2);
            }
        }
        ready=1;
        /*
        var a:Number = 0;
        var b:int = 0;
        for(i=0;i<rotArr.length;i++) {
        var img:DisplayImage = rotArr[i];
        _screen.copyPixels(img.bmp,img.rect,new Point((a-b*10)*img.rect.width,b * img.rect.height));
        a += 1;
        b = a/10 ;
        }*/
        
        //planeBitmap = new Bitmap;
        //_mainScreen.addChild(planeBitmap);
    }
    
    public function update():void {
        if (!ready)
            return;
        var a:Number;
        
        // rotation
        var d:Number = MoveControl.direction-r;
        if(d < -180) d = 360 + d;
        else if(d > 180) d = d - 360;
        r += d*0.1;
        MoveControl.planeDirection = r;
        
        // move
        var theta:Number = (270 - r) * D2R;
        v += (MoveControl.speed-v)*0.1
        x+=v * Math.sin(theta);
        y+=v * Math.cos(theta);
        
        // check boundary
        (x > WIDTH) ? x=0 : (x < 0) ? x=WIDTH : 0;
        (y > HEIGHT) ? y=0 : (y < 0) ? y=HEIGHT : 0;
        
        // find image
        var i:Number = r-90;
        i = i - Math.floor(i/360) * 360;
        currentImg=rotArr[int(i * ROT_STEP_DIRECTION) + ROT_STEPS * currentFrame];
        
        // check frame
        if (frameInterval + 100 < getTimer()) {
            if (++currentFrame === FRAMES) {
                currentFrame=0;
            }
            frameInterval=getTimer();
        }
        
        
    }
    
    public function render():void {
        if (!ready)
            return;
        _screen.copyPixels(currentImg.bmp, currentImg.rect, new Point(x - currentImg.cx, y - currentImg.cy));
    }
}

// Background
//----------------------------------------------------------------------------------------------------
class Landscape extends Bitmap {
    // This color gradation is refered from psyrak's BumpyPlanet
    // http://wonderfl.net/code/d79cd85845773958620f42cb3e6cb363c2020c73
    public var gradation:*={color: [0x000080, 0x0066ff, 0xcc9933, 0x00cc00, 0x996600, 0xffffff], alpha: [100, 100, 100, 100, 100, 100], ratio: [0, 96, 96, 128, 168, 192]};
    public var pixels:BitmapData, texture:BitmapData, rect:Rectangle;
    private var pt:Point=new Point();
    
    function Landscape(w:int, h:int) {
        texture=new BitmapData(w * 2, h * 2, false, 0);
        pixels=new BitmapData(w, h, false, 0);
        rect=new Rectangle(0, 0, w, h);
        super(pixels);
        
        // height map
        var hmap:BitmapData=new BitmapData(w, h, false, 0);
        hmap.perlinNoise(w * 0.5, h * 0.5, 10, Math.random() * 0xffffffff, true, false, 0, true);
        hmap.colorTransform(hmap.rect, new ColorTransform(1.5, 1.5, 1.5, 1, -64, -64, -64, 0));
        
        // texture
        var mapR:Array=new Array(256), mapG:Array=new Array(256), mapB:Array=new Array(256);
        var gmap:BitmapData=new BitmapData(256, 1, false, 0), render:Shape=new Shape(), mat:Matrix=new Matrix();
        mat.createGradientBox(256, 1, 0, 0, 0);
        render.graphics.clear();
        render.graphics.beginGradientFill("linear", gradation.color, gradation.alpha, gradation.ratio, mat);
        render.graphics.drawRect(0, 0, 256, 1);
        render.graphics.endFill();
        gmap.draw(render);
        for (var i:int=0; i < 256; i++) {
            var col:uint=gmap.getPixel(i, 0);
            mapR[i]=col & 0xff0000;
            mapG[i]=col & 0x00ff00;
            mapB[i]=col & 0x0000ff;
        }
        gmap.dispose();
        mat.identity();
        texture.paletteMap(hmap, hmap.rect, hmap.rect.topLeft, mapR, mapG, mapB);
        
        // shading
        var smap:BitmapData=new BitmapData(w, h, false, 0);
        smap.applyFilter(hmap, hmap.rect, hmap.rect.topLeft, new ConvolutionFilter(3, 3, [-1, -1, 0, -1, 0, 1, 0, 1, 1], 1, 0, true, true));
        texture.draw(smap, null, new ColorTransform(4, 4, 4, 1, 160, 160, 160, 0), "multiply");
        
        // copy 2x2
        pt.x=w;
        pt.y=h;
        texture.copyPixels(texture, hmap.rect, pt);
        pt.x=0;
        pt.y=h;
        texture.copyPixels(texture, hmap.rect, pt);
        pt.x=w;
        pt.y=0;
        texture.copyPixels(texture, hmap.rect, pt);
        pt.x=0;
        pt.y=0;
        
        // rendering
        pixels.copyPixels(texture, rect, pt);
    }
}

/** Base64 */
class Base64 {   
    private static  const encodeChars:Array =    
        ['A','B','C','D','E','F','G','H',   
            'I','J','K','L','M','N','O','P',   
            'Q','R','S','T','U','V','W','X',   
            'Y','Z','a','b','c','d','e','f',   
            'g','h','i','j','k','l','m','n',   
            'o','p','q','r','s','t','u','v',   
            'w','x','y','z','0','1','2','3',   
            '4','5','6','7','8','9','+','/'];   
    private static  const decodeChars:Array =    
        [-1, -1, -1, -1, -1, -1, -1, -1,   
            -1, -1, -1, -1, -1, -1, -1, -1,   
            -1, -1, -1, -1, -1, -1, -1, -1,   
            -1, -1, -1, -1, -1, -1, -1, -1,   
            -1, -1, -1, -1, -1, -1, -1, -1,   
            -1, -1, -1, 62, -1, -1, -1, 63,   
            52, 53, 54, 55, 56, 57, 58, 59,   
            60, 61, -1, -1, -1, -1, -1, -1,   
            -1,  0,  1,  2,  3,  4,  5,  6,   
            7,  8,  9, 10, 11, 12, 13, 14,   
            15, 16, 17, 18, 19, 20, 21, 22,   
            23, 24, 25, -1, -1, -1, -1, -1,   
            -1, 26, 27, 28, 29, 30, 31, 32,   
            33, 34, 35, 36, 37, 38, 39, 40,   
            41, 42, 43, 44, 45, 46, 47, 48,   
            49, 50, 51, -1, -1, -1, -1, -1];   
    public static function encode(data:ByteArray):String {   
        var out:Array = [];   
        var i:int = 0;   
        var j:int = 0;   
        var r:int = data.length % 3;   
        var len:int = data.length - r;   
        var c:int;   
        while (i < len) {   
            c = data[i++] << 16 | data[i++] << 8 | data[i++];   
            out[j++] = encodeChars[c >> 18] + encodeChars[c >> 12 & 0x3f] + encodeChars[c >> 6 & 0x3f] + encodeChars[c & 0x3f];   
        }   
        if (r == 1) {   
            c = data[i++];   
            out[j++] = encodeChars[c >> 2] + encodeChars[(c & 0x03) << 4] + "==";   
        }   
        else if (r == 2) {   
            c = data[i++] << 8 | data[i++];   
            out[j++] = encodeChars[c >> 10] + encodeChars[c >> 4 & 0x3f] + encodeChars[(c & 0x0f) << 2] + "=";   
        }   
        return out.join('');   
    }   
    public static function decode(str:String):ByteArray {   
        var c1:int;   
        var c2:int;   
        var c3:int;   
        var c4:int;   
        var i:int;   
        var len:int;   
        var out:ByteArray;   
        len = str.length;   
        i = 0;   
        out = new ByteArray();   
        while (i < len) {   
            // c1   
            do {   
                c1 = decodeChars[str.charCodeAt(i++) & 0xff];   
            } while (i < len && c1 == -1);   
            if (c1 == -1) {   
                break;   
            }   
            // c2       
            do {   
                c2 = decodeChars[str.charCodeAt(i++) & 0xff];   
            } while (i < len && c2 == -1);   
            if (c2 == -1) {   
                break;   
            }   
            out.writeByte((c1 << 2) | ((c2 & 0x30) >> 4));   
            // c3   
            do {   
                c3 = str.charCodeAt(i++) & 0xff;   
                if (c3 == 61) {   
                    return out;   
                }   
                c3 = decodeChars[c3];   
            } while (i < len && c3 == -1);   
            if (c3 == -1) {   
                break;   
            }   
            out.writeByte(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2));   
            // c4   
            do {   
                c4 = str.charCodeAt(i++) & 0xff;   
                if (c4 == 61) {   
                    return out;   
                }   
                c4 = decodeChars[c4];   
            } while (i < len && c4 == -1);   
            if (c4 == -1) {   
                break;   
            }   
            out.writeByte(((c3 & 0x03) << 6) | c4);   
        }   
        return out;   
    }   
}