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

Invaders

Get Adobe Flash player
by royi 01 Aug 2015
/**
 * Copyright royi ( http://wonderfl.net/user/royi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/1t2o
 */

package  {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.filters.BlurFilter;
    import flash.filters.DisplacementMapFilter;
    import flash.filters.DisplacementMapFilterMode;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.utils.Dictionary;
    
    [SWF(width=465, height=465, frameRate=60, backgroundColor=0x000000)]
    public class Invaders extends Sprite {
        
        private static const PLAYER           :String = "player",
                             ALIEN            :String = "alien",
                             SHIELD           :String = "shield",
                             UFO              :String = "ufo",
                             BULLET           :String = "bullet",
                             ALIEN_BULLET     :String = "alienBullet";
        
        private static const SCALE:int = 3;
        private static const ALIEN_W:int = 9;
        private static const ALIEN_H:int = 7;
        private static const ALIEN_ROWS:int = 5;
        private static const ALIEN_COLS:int = 11;
        private static const PLAYER_W:int = 11;
        private static const PLAYER_H:int = 7;
        private static const SHIELD_W:int = 17;
        private static const SHIELD_H:int = 12;
        
        private var alienSpeedX:int = 4; // aliens move this many pixels each tick
        private var alienSpeedY:int = 4; // aliens descend this many pixels
        private var alienSpacingX:int = 2; // pixels of spaaace between aliens
        private var alienSpacingY:int = 5;
        private var alienVX:int = 0, alienVY:int = 0; // alien velocity
        
        private var alienDrop:Boolean;
        private var alienCluster:Rectangle = new Rectangle(); // matches the size of whole alien grid
        private var gameBounds:Rectangle = new Rectangle(2, 20, 151, 125); // aliens can only move within bounds
        
        private var particles:Array = [];
        private var gravity:Number = .15; // only particles are affected
        
        // gfx
        private var baseColor:uint = 0xff00ff00;
        private var canvas:BitmapData; // main canvas for drawing game
        private var canvasBig:BitmapData; // visible canvas enlarged
        private var sw:int, sh:int; // stage width/height
        private var cw:int, ch:int; // canvas width/height
        private var gfx:Object = { }; // list of all graphics (bitmapData)
        private var floorRect:Rectangle = new Rectangle(2, 145, 151, 1); // floor size/position
        private var scaleMatrix:Matrix = new Matrix();
        private var alienColors:Array = [0xffff0000, 0xff00ff00, 0xff0000ff,
                                         0xffffff00, 0xff00ffff, 0xffff00ff];
        private var filter:DisplacementMapFilter;
        
        // input
        private var keyDown:Dictionary = new Dictionary(); // keeps track of keys pressed
        
        private var paused:Boolean = true;
        private var newGame:Boolean;
        private var initTick:int; // init in startGame()
        private var tick:int;
        private var frame:int; // frame 0/1
        private var lives:int;
        private var score:int;
        private var playerSpeed:int;
        private var player:Entity;
        private var playerBullet:Rectangle = new Rectangle(0, 0, 1, 4);
        private var playerBulletSpeed:int;
        private var playerBulletActive:Boolean = false;
        private var aliensMoving:Boolean = true; // stops/starts all aliens
        private var aliens:Array = [];
        private var shields:Array = [];
        private var numAliens:int;
        private var menu:Boolean = true;
        private var shieldGraphics:BitmapData;
        private var numShields:int = 4;
        private var shieldsY:int = 117;
        private var alienBullet:Entity;
        private var alienBulletFrame:int;
        private var scanLines:BitmapData;
        
        /* INIT
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
        public function Invaders() {
            sw = stage.stageWidth, sh = stage.stageHeight;
            cw = sw / SCALE, ch = sh / SCALE;
            canvas = new BitmapData(cw, ch, false, 0x000000);
            
            canvasBig = new BitmapData(sw, sh, false, 0x000000);
            var bmp:Bitmap = new Bitmap(canvasBig);
            addChild(bmp);
            
            scaleMatrix.scale(SCALE, SCALE);
            
            // displacement map filter
            var mapBitmapData:BitmapData = new BitmapData(sw, sh, false, 0x888888);
            var mapSprite:Sprite = new Sprite();
            mapSprite.graphics.beginFill(0xff0000);
            mapSprite.graphics.drawRect(0, 0, sw, sh);
            mapSprite.graphics.endFill();
            mapSprite.graphics.beginFill(0x800000);
            mapSprite.graphics.drawRoundRect(2, 2, sw-4, sh-4, 100);
            mapSprite.graphics.endFill();
            mapBitmapData.draw(mapSprite);
            var blur:BlurFilter = new BlurFilter(50, 50, 3);
            mapBitmapData.applyFilter(mapBitmapData, mapBitmapData.rect, new Point(), blur);
            var mapBitmap:Bitmap = new Bitmap(mapBitmapData);
            //addChild(mapBitmap);
            //DisplacementMapFilterMode.
            //BitmapDataChannel.
            filter = new DisplacementMapFilter(mapBitmapData, new Point(), 1, 1, 20, 20, "clamp", 0xff0000, 1);
            scanLines = new BitmapData(sw, sh, true, 0x00000000);
            for (var i:int = 0; i < sh; i += SCALE) {
                scanLines.fillRect(new Rectangle(0, i, sw, 1), 0x22000000);
                scanLines.fillRect(new Rectangle(0, i+1, sw, 1), 0x22ffffff);
            }
            
            // populate gfx object with generated graphics
            gfx[PLAYER] = newPlayerGfx();
            for (i = 1; i <= ALIEN_ROWS; i++)
                gfx[ALIEN + i] = randomAlienGfx();
            gfx[ALIEN_BULLET] = newAlienBulletGfx();
            
            // create entities
            var shieldsWidth:int = (gameBounds.width / numShields) * (numShields-1)+(SHIELD_W);
            for (i = 0; i < numShields; i++) {
                gfx[SHIELD + (i+1)] = newShieldGfx();
                shields[i] = new Entity(SHIELD + (i+1));
                shields[i].x = ((gameBounds.width / numShields) * i) + ((cw-shieldsWidth)*.5);
                shields[i].y = shieldsY;
                trace(shields[i].x);
            }
            
            alienBullet = new Entity(ALIEN_BULLET);
            alienBullet.active = false;
            
            player = new Entity(PLAYER);
            player.y = floorRect.y - PLAYER_H - 1;
            player.active = false;
            
            numAliens = ALIEN_ROWS * ALIEN_COLS;
            for (i = 0; i < numAliens; i++)
                aliens[i] = new Entity(ALIEN + (i % ALIEN_ROWS + 1));
            
            startGame();
            
            tick = initTick;
            addEventListener(Event.ENTER_FRAME, loop);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
        }
        
        /* START GAME
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
        private function startGame():void {
            menu = false;
            paused = false;
            newGame = true; // set state
            player.active = false;
            alienDrop = true;
            alienBullet.active = false;
            frame = 0;
            lives = 2;
            score = 0;
            playerSpeed = 1;
            playerBulletSpeed = 3;
            initTick = numAliens;
            
            with (alienCluster) { // TODO: set proper x/y
                width = (ALIEN_COLS * (ALIEN_W + alienSpacingX)) - alienSpacingX;
                height = (ALIEN_ROWS * (ALIEN_H + alienSpacingY)) - alienSpacingY;
                x = alienSpacingX;
                y = -alienCluster.height;
            }
            
            // position aliens
            for (var i:int = 0; i < numAliens; i++) {
                var col:int = i % ALIEN_ROWS;
                var row:int = i % ALIEN_COLS;
                aliens[i].active = true;
                aliens[i].x = (ALIEN_W + alienSpacingX) * row + alienSpacingX;
                aliens[i].y = (ALIEN_H + alienSpacingY) * col - alienCluster.height;
            }
        }
        
        /* LOOP
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
        private function loop(e:Event):void {
            if (paused) return;
            
            // draw background
            canvas.fillRect(canvas.rect, 0x000000);
            //canvas.fillRect(gameBounds, 0x000033);
            //canvas.fillRect(alienCluster, 0x330033);
            
            if (menu) return; // don't draw the rest if in menu
            
            if (newGame) { // if new game state, play intro
                alienDrop = false;
                alienBullet.active = false;
                player.x = (cw - PLAYER_W) * .5;
                
                if (alienCluster.top >= gameBounds.top) {
                    newGame = false;
                    player.active = true;
                    alienDrop = true;
                    tick = initTick;
                } else {
                    tick = 1; // tick repeatedly
                }
            }
            
            if (tick == 0) {
                tick = initTick;
                if (frame == 0) frame = 1;
                else frame = 0;
            }
            tick--;
            
            // draw particles
            for (i = 0; i < particles.length; i++) {
                if (particles[i][6] == false) continue;
                
                particles[i][2] *= .98;
                particles[i][3] *= .96;
                particles[i][3] += gravity;
                particles[i][0] += particles[i][2];
                particles[i][1] += particles[i][3];
                
                if (particles[i][1] > floorRect.y - 1) {
                    particles[i][1] = floorRect.y-1;
                    if (particles[i][5] < 1) {
                        particles[i][3] = -particles[i][3];
                        particles[i][5]++;
                    } else {
                        particles[i][6] = false;
                    }
                }
                canvas.setPixel(particles[i][0], particles[i][1], particles[i][4]);
            }
            
            // move player
            if (player.active) {
                if (keyDown[37]) { // left
                    player.x -= playerSpeed;
                }
                if (keyDown[39]) { // right
                    player.x += playerSpeed;
                }
                
                if (player.x < gameBounds.left) {
                    player.x = gameBounds.left;
                } else if (player.x > gameBounds.right - PLAYER_W) {
                    player.x = gameBounds.right - PLAYER_W;
                }
                
                if (playerBulletActive) {
                    playerBullet.y -= playerBulletSpeed;
                    if (playerBullet.y < gameBounds.top) {
                        playerBulletActive = false;
                    }
                    
                    // draw bullet
                    canvas.fillRect(playerBullet, Math.random() * uint.MAX_VALUE);
                } else {
                    if (keyDown[32]) { // space
                        playerBulletActive = true;
                        playerBullet.x = player.x + int(PLAYER_W * .5);
                        playerBullet.y = player.y;
                    }
                }
            }
            
            // draw alien bullet
            if (alienBullet.active && player.active) {
                alienBullet.y++;
                if (alienBulletFrame == 0) alienBulletFrame = 1;
                else alienBulletFrame = 0;
                if (alienBullet.y > gameBounds.bottom - 4) {
                    alienBullet.y > gameBounds.bottom - 4;
                    alienBullet.active = false;
                }
                canvas.copyPixels(gfx[ALIEN_BULLET][alienBulletFrame], gfx[ALIEN_BULLET][alienBulletFrame].rect, alienBullet.pos);
            } else if (!alienBullet.active && player.active) {
                var randAlien:int = Math.random() * aliens.length;
                for (var k:int = randAlien; k < aliens.length; k++) {
                    if (!aliens[k].active) continue;
                    alienBullet.x = aliens[k].x + (ALIEN_W * .5) -1;
                    alienBullet.y = aliens[k].y + ALIEN_H;
                    alienBullet.active = true;
                    break;
                }
            }
            
            // if bullet hit shield
            for (i = 0; i < numShields; i++) {
                var bulletHitShield:Boolean = gfx[SHIELD + (i+1)][0].hitTest(shields[i].pos,
                                                                            255,
                                                                            playerBullet);
                if (bulletHitShield) {
                    damage(shields[i], new Point(playerBullet.x, playerBullet.top));
                    playerBulletActive = false;
                    trace("bullet hit shield");
                }
                
                var alienBulletHitShield:Boolean = gfx[SHIELD + (i + 1)][0].hitTest(shields[i].pos,
                                                                                    255,
                                                                                    gfx[ALIEN_BULLET][alienBulletFrame],
                                                                                    alienBullet.pos,
                                                                                    255)
                
                if (alienBulletHitShield) {
                    damage(shields[i], new Point(alienBullet.x, alienBullet.y+2));
                    alienBullet.active = false;
                }
            }
            
            if (tick == 0) {
                if (alienCluster.right >= gameBounds.right) {
                    if (alienDrop == false) {
                        alienDrop = true;
                        alienVY = alienSpeedY;
                    } else {
                        alienDrop = false;
                        alienVY = 0;
                    }
                    alienVX = -alienSpeedX;
                } else if (alienCluster.left <= gameBounds.left) {
                    if (alienDrop == false) {
                        alienDrop = true;
                        alienVY = alienSpeedY;
                    } else {
                        alienDrop = false;
                        alienVY = 0;
                    }
                    alienVX = alienSpeedX;
                } else {
                    alienDrop = false;
                    alienVY = 0;
                }
                
                if (!alienDrop) alienCluster.x += alienVX;
                else alienCluster.y += alienVY;
            }
            
            // draw floor
            canvas.fillRect(floorRect, baseColor);
            
            // draw shields
            for (var i:int = 0; i < numShields; i++) {
                canvas.copyPixels(gfx[SHIELD + (i+1)][0], gfx[SHIELD + (i+1)][0].rect, shields[i].pos);
            }
            
            // draw aliens
            for (i = 0; i < numAliens; i++) {
                if (!aliens[i].active) continue;
                
                var bmpData:BitmapData = gfx[ ALIEN + (i % ALIEN_ROWS + 1) ][frame];
                if (aliensMoving && tick == 0) {
                    if (!alienDrop) aliens[i].x += alienVX;
                    else aliens[i].y += alienVY;
                }
                
                // if alien hit player, game over
                if (player.active) {
                    var alienHitPlayer:Boolean = gfx[aliens[i].gfxId][frame].hitTest(aliens[i].pos,
                                                                                     255,
                                                                                     gfx[PLAYER][0],
                                                                                     player.pos,
                                                                                     255);
                    
                    if (alienHitPlayer) {
                        gameOver();
                    }
                }
                
                // if alien hit shield
                for (var j:int = 0; j < numShields; j++) {
                    var alienHitShield:Boolean = gfx[aliens[i].gfxId][frame].hitTest(aliens[i].pos,
                                                                                     255,
                                                                                     gfx[SHIELD + (j+1)][0],
                                                                                     shields[j].pos,
                                                                                     255);
                    if (alienHitShield) {
                        subtractPixels(shields[j], aliens[i]);
                    }
                }
                
                // explode alien if hit by player bullet
                var bulletHitAlien:Boolean = gfx[aliens[i].gfxId][frame].hitTest(aliens[i].pos,
                                                                                 255,
                                                                                 playerBullet);
                if (playerBulletActive && bulletHitAlien) {
                    aliens[i].active = false;
                    playerBulletActive = false;
                    explode(aliens[i]);
                    recalculateAlienCluster();
                    if (initTick > 1)
                        initTick--;
                    else
                        trace("max speed reached");
                }
                
                canvas.copyPixels(bmpData,
                                  bmpData.rect,
                                  aliens[i].pos);
            }
            
            // draw player
            if (player.active) {
                canvas.copyPixels(gfx[PLAYER][0], gfx[PLAYER][0].rect, player.pos);
                
                var alienBulletHitPlayer:Boolean = gfx[PLAYER][0].hitTest(player.pos,
                                                                          255,
                                                                          gfx[ALIEN_BULLET][alienBulletFrame],
                                                                          alienBullet.pos,
                                                                          255)
                
                if (alienBulletHitPlayer) {
                    gameOver();
                    alienBullet.active = false;
                }
            }
            
            // draw lives
            for (i = 0; i < lives; i++)
                canvas.copyPixels(gfx[PLAYER][0], gfx[PLAYER][0].rect, new Point((i * (PLAYER_W + 2) + gameBounds.x), floorRect.bottom + 1));
            
            // scale and draw final image
            canvasBig.draw(canvas, scaleMatrix);
            canvasBig.draw(scanLines);
            canvasBig.applyFilter(canvasBig, canvasBig.rect, new Point(), filter);
        }
        
        /* GAME OVER
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
        private function gameOver():void {
            lives--;
            player.active = false;
            explode(player, false);
            aliensMoving = false;
            if (lives < 0) {
                lives = 0;
                trace("GAME OVER");
            }
            trace("-1 LIFE");
        }
        
        /* RECALCULATE ALIEN CLUSTER BOUNDS
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
        private function recalculateAlienCluster():void {
            var left:int = cw;
            var right:int = 0;
            var top:int = ch;
            var bottom:int = 0;
            for (var i:int = 0; i < numAliens; i++) {
                if (aliens[i].active) {
                    if (aliens[i].x < left) left = aliens[i].x;
                    if (aliens[i].x > right) right = aliens[i].x + ALIEN_W;
                    if (aliens[i].y < top) top = aliens[i].y;
                    if (aliens[i].y > bottom) bottom = aliens[i].y + ALIEN_H;
                }
            }
            alienCluster.x = left;
            alienCluster.y = top;
            alienCluster.width = right-left;
            alienCluster.height = bottom-top;
        }
        
        /* SUBTRACT PIXELS AROUND DAMAGE POINT
         * (ONLY FROM NON ANIMATED)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
        private function damage(entity:Entity, point:Point):void {
            var damageSquare:int = 4;
            var relX:int = point.x - entity.x;
            var relY:int = point.y - entity.y;
            var rndX:int;
            var rndY:int;
            for (var x:int = 0; x < damageSquare; x++) {
                for (var y:int = 0; y < damageSquare; y++) {
                    rndX = (Math.random() * damageSquare) - (damageSquare * .5);
                    rndY = (Math.random() * damageSquare) - (damageSquare * .5);
                    gfx[entity.gfxId][0].setPixel32(rndX+relX+x, rndY+relY+y, 0x00000000);
                }
            }
        }
        
        /* SUBTRACT PIXELS (ONLY FROM NON ANIMATED)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
        private function subtractPixels(fromEntity:Entity, withEntity:Entity, withAnimated:Boolean = true):void {
            var frame:int = 0;
            if (withAnimated) frame = this.frame;
            var relX:int = withEntity.x - fromEntity.x;
            var relY:int = withEntity.y - fromEntity.y;
            var width:int = gfx[withEntity.gfxId][frame].width;
            var height:int = gfx[withEntity.gfxId][frame].height;
            for (var x:int = 0; x < width; x++) {
                for (var y:int = 0; y < height; y++) {
                    var color:uint = gfx[withEntity.gfxId][frame].getPixel(x, y);
                    if (color) {
                        gfx[fromEntity.gfxId][0].setPixel32(relX+x, relY+y, 0x00000000);
                    }
                }
            }
        }
        
        /* EXPLODE INTO PARTICLES
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
        private function explode(obj:Object, animated:Boolean = true):void {
            var frame:int = 0;
            if (animated) frame = this.frame;
            var width:int = gfx[obj.gfxId][frame].width;
            var height:int = gfx[obj.gfxId][frame].height;
            for (var i:int = 0; i < width; i++) {
                                for (var j:int = 0; j < height; j++) {
                    var color:uint = gfx[obj.gfxId][frame].getPixel(i, j);
                    if (color) {
                        if (Math.random() < .7)
                            particles.push([obj.pos.x+i, obj.pos.y+j, 0, 0, 0x333333, 0, true]);
                        else
                            particles.push([obj.pos.x+i, obj.pos.y+j, (Math.random() - .5) * 4, (Math.random() - .8) * 4, 0x333333, 0, true] );
                    }
                }
            }
        }
        
        /* GFX
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
        private function newPlayerGfx():Array {
            var bmpData:BitmapData = new BitmapData(15, 7, true, 0x00000000);
            with (bmpData) {
                setPixel32(5, 0, baseColor);
                setPixel32(4, 1, baseColor);
                setPixel32(5, 1, baseColor);
                setPixel32(6, 1, baseColor);
                fillRect(new Rectangle(1, 2, 9, 1), baseColor);
                fillRect(new Rectangle(0, 3, 11, 4), baseColor);
            }
            return [bmpData];
        }
        
        private function newAlienBulletGfx():Array {
            var color:uint = 0xffff0000;
            
            var frame1:BitmapData = new BitmapData(2, 4, true, 0x00000000);
            var frame2:BitmapData = new BitmapData(2, 4, true, 0x00000000);
            with (frame1) {
                setPixel32(0, 0, color);
                setPixel32(1,1,color);
                setPixel32(0,2,color);
                setPixel32(1,3,color);
            }
            with (frame2) {
                setPixel32(1,0,color);
                setPixel32(0,1,color);
                setPixel32(1,2,color);
                setPixel32(0,3,color);
            }
            return [frame1, frame2];
        }
        
        private function newShieldGfx():Array {
            var bmpData:BitmapData = new BitmapData(17, 12, true, 0x00000000);
            with (bmpData) {
                fillRect(new Rectangle(4, 0, 9, 1), baseColor);
                fillRect(new Rectangle(3, 1, 4, 1), baseColor);
                fillRect(new Rectangle(10, 1, 4, 1), baseColor);
                fillRect(new Rectangle(2, 2, 4, 1), baseColor);
                fillRect(new Rectangle(11, 2, 4, 1), baseColor);
                fillRect(new Rectangle(1, 3, 5, 1), baseColor);
                fillRect(new Rectangle(11, 3, 5, 1), baseColor);
                fillRect(new Rectangle(0, 4, 7, 1), baseColor);
                fillRect(new Rectangle(10, 4, 7, 1), baseColor);
                fillRect(new Rectangle(0, 5, 8, 1), baseColor);
                fillRect(new Rectangle(9, 5, 8, 1), baseColor);
                fillRect(new Rectangle(0, 6, 17, 1), baseColor);
                fillRect(new Rectangle(0, 7, 7, 1), baseColor);
                fillRect(new Rectangle(10, 7, 7, 1), baseColor);
                fillRect(new Rectangle(0, 8, 5, 1), baseColor);
                fillRect(new Rectangle(12, 8, 5, 1), baseColor);
                fillRect(new Rectangle(0, 9, 4, 3), baseColor);
                fillRect(new Rectangle(13, 9, 4, 3), baseColor);
                setPixel32(7, 2, baseColor);
                setPixel32(9, 2, baseColor);
                setPixel32(8, 4, baseColor);
            }
            return [bmpData];
        }
        
        // generate 2-frame alien graphic (picks random top/mid/bottom)
        private function randomAlienGfx():Array {
            
            var rndColor:int = Math.random() * alienColors.length;
            var color:uint = alienColors[rndColor];
            
            var tops:Array = [[2,0,6,0,3,1,5,1],
                              [2,0,6,0,3,1,5,1],
                              [4,0,3,1,4,1,5,1],
                              [4,0,3,1,4,1,5,1]];
                              
            var mids:Array = [[2,2,3,2,4,2,5,2,6,2,1,3,2,3,4,3,6,3,7,3,0,4,8,4,0,5,8,5],
                              [0,1,8,1,0,2,2,2,3,2,4,2,5,2,6,2,8,2,1,3,2,3,4,3,6,3,7,3],
                              [2,2,3,2,4,2,5,2,6,2,2,3,4,3,6,3],
                              [2,2,3,2,4,2,5,2,6,2,2,3,4,3,6,3]];
                              
            var btms:Array = [[2,4,3,4,4,4,5,4,6,4,2,5,6,5,3,6,5,6],
                              [2,4,3,4,4,4,5,4,6,4,2,5,6,5,1,6,7,6],
                              [3,4,5,4,2,5,4,5,6,5,2,6,6,6],
                              [3,4,4,4,5,4,2,5,6,5,3,6,5,6]];
                              
            var frames:Array = [];
            frames[0] = new BitmapData(ALIEN_W, ALIEN_H, true, 0x00000000);
            frames[1] = new BitmapData(ALIEN_W, ALIEN_H, true, 0x00000000);
            
            function addPart(part:Array):void {
                var rnd:int = int(Math.random() * (part.length / 2)) * 2;
                for (var i:int = 0; i < part[rnd].length; i+=2) {
                    frames[0].setPixel32(part[rnd][i], part[rnd][i+1], color);
                }
                for (i = 0; i < part[rnd+1].length; i+=2) {
                    frames[1].setPixel32(part[rnd+1][i], part[rnd+1][i+1], color);
                }
            }
            addPart(tops);
            addPart(mids);
            addPart(btms);
            
            return frames;
        }
        
        /* KEYBOARD EVENTS
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
        private function onKeyDown(e:KeyboardEvent):void {
            keyDown[e.keyCode] = true;
            
            // start game
            if (menu)
                startGame();
        }
        private function onKeyUp(e:KeyboardEvent):void { delete keyDown[e.keyCode]; }
    }
}

import flash.geom.Point;

class Entity extends Object {
    public var pos:Point = new Point();
    public var active:Boolean = true;
    public var gfxId:String;
    
    // pass the key for the graphics you want to use from the gfx dictionary
    public function Entity(gfxId:String) {
        this.gfxId = gfxId;
    }
    
    public function set x(value:Number):void { pos.x = value; }
    public function get x():Number { return pos.x; }
    public function set y(value:Number):void { pos.y = value; }
    public function get y():Number { return pos.y; }
}