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

Space iVaders

Attempt to build a Simple Space Invaders in one session 
(3 hours + couple of extra for bug fixes and extras)

Left and Right arrow keys to move.
Space to fire

Used some pixel graphic code from the Professional Fladdict comp.

...
@author Swingpants
Get Adobe Flash player
by swingpants 28 Jul 2009
  • Related works: 4
  • Talk

    sketchbookgames at 27 Jul 2009 20:58
    holding the up arrow will break the game. things that could be added: if a column is destroyed it stops shooting.. horde only bounces back when a surviving column hits wall, visual count down of respawn delay, victory screen. very nicely done as is though!
    makc3d at 27 Jul 2009 21:51
    bullets disappear soon after you start playing for some reason, then my cannon too
    makc3d at 27 Jul 2009 21:57
    ...I guess that's up arrow issue. also invisible enemies keep shooting even after I kill everybody
    swingpants at 28 Jul 2009 00:18
    Thanks for the responses guys. I challenged myself to build Space Invaders (lite) in less than 3 hours. There were a few bugs in there - your spotted the bullet dissappearing one - that was a bullet overlaying another and removing the canvas. I've updated the conditional now to fix this. Also fixed the invisible bombers, added a saucer, and will add an acceleration to the ivaders to speed them up over time.
    makc3d at 30 Jul 2009 17:36
    now at some point invaders stop moving and shooting

    Tags

    Embed
/**
 * Copyright swingpants ( http://wonderfl.net/user/swingpants )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/7Mm4
 */

package 
{
/**********************************************************
Attempt to build a Simple Space Invaders in one session 
(3 hours + couple of extra for bug fixes and extras)

 Left and Right arrow keys to move.
 Space to fire
 
 Used some pixel graphic code from the Professional Fladdict comp.
***********************************************************/
	import flash.display.Sprite;
	import flash.display.MovieClip;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.KeyboardEvent
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.ui.Keyboard;
	
	import caurina.transitions.Tweener;
	
	/**
	 * ...
	 * @author Swingpants
	 */
[SWF(width=450, height=450, backgroundColor=0x000000)]   
 	public class Main extends Sprite 
	{
		
		private const screenW:int = 450
		private const screenH:int = 450
		
		private var cols:Array = []
		private var rightmost_col:int = 0
		private var leftmost_col:int = 9999
		private var bottom_most:int=0
		
		private var tank:Bitmap
		
		private var saucer:Bitmap
		private var saucer_flying:Boolean = false
		private var saucer_speed:int = 2
	
		private var vader1:BitmapData
		private var vader2:BitmapData
		private var next:BitmapData;
		private var pattern:BitmapData;
		
		private var anim_count:int = 0
		private var anim_speed:int = 21
		private var max_anim_speed:int = 21
		private var min_anim_speed:int = 7
		private var ivader_dir:int = 2
		private var ivader_max_speed:int=7
		private var num_in_row:int = screenW / 30
		private var num_in_col:int = 12
		
		private var tf:TextField = new TextField()
		
		private var y_drop:int=0
		private var tank_speed:int = 2
		private var bullet_speed:int = 4
		private var max_bullets:int = 5
		private var max_bombs:int = 5
		private var bomb_ratio:Number=0.92
		
		private var leftFlag:Boolean = false
		private var rightFlag:Boolean = false
		private var spaceFlag:Boolean = false
		
		private var tank_bullets:Array = []
		private var vader_bombs:Array = []
		
		private var canvas:Sprite = new Sprite()
		
		private var lives_left:int = 3
		private var score:int = 0
		
		private var cease_fire:Boolean = false
		
		private var ivader_count:int = 0
		private var ivaders_down:int = 0
		
		
	public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
	private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
			stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
			
			 //generate bitmap pattern.
			vader1 = fig1();
			vader2 = fig2();

			pattern = vader1.clone();
			next    = vader2;
			
			for (var i:int = 0; i < num_in_row; i++)
				{
					cols.push(initIVaderCol(50 + i * 20, pattern))
					if (pattern == vader1) pattern = vader2
						else pattern=vader1
				}
			
			tank = new Bitmap(tankBmd())
			tank.x = screenW * 0.5
			tank.y = screenH-50
			addChild(tank)
			
			saucer = new Bitmap(saucerBmd())
			saucer.name = "ivader_saucer"
			saucer.x=-999
			saucer.y = 20
			addChild(saucer)
			
			canvas.name="canvas"
			addChild(canvas)
			
			tf.textColor = 0xFFFFFF
			renderScore()
			
			addChild(tf)
			
			initParams()
			
			addEventListener(Event.ENTER_FRAME, update)
		}
		
	private function initParams():void
		{
			ivader_dir = 2
			anim_speed = 21
			tank_speed = 2
			bomb_ratio = 0.92
			lives_left = 3
			max_bombs = 5
			ivaders_down = 0
			bottom_most=0
		}
		
	private function resetVaders():void
		{
			var len:int = cols.length
			for (var i:int = 0; i < len; i++)
				{
					for (var j:int = 0; j < num_in_col; j++)
						{
							cols[i][j].x = 50 + i * 20
							cols[i][j].y = 50 + 20 * j
							addChild(cols[i][j])
						}
				}
			max_bombs++
			bomb_ratio*=.92
		}
		
	private function renderScore():void
		{
			tf.text = "LIVES:"+lives_left+"\nSCORE:"+score
		}
		
		
	private function initIVaderCol(x_val:int, bmd:BitmapData):Array
		{
			var arr:Array=[]
			for (var i:int = 0; i < num_in_col; i++)
				{
					var bmp:Bitmap = new Bitmap(bmd)
					bmp.name="ivader"+ivader_count
					bmp.x=x_val
					bmp.y = 50+20 * i
					arr.push(bmp)
					addChild(bmp)
					
					ivader_count++
				}
			return arr
		}
		
	
		
//***************************MAIN LOOP***************************
	private function update(e:Event):void
		{
			anim_count++
			if (anim_count == anim_speed)
				{
					anim_count = 0
					var len:int = cols.length
					leftmost_col = 999
					rightmost_col = -999
					for (var i:int = 0; i < len; i++)
						{
							if (updateIVaderCol(cols[i]))
								{
									if (leftmost_col > i) leftmost_col = i
									if (rightmost_col < i) rightmost_col = i
								}
						}
					if (leftmost_col != 999 && rightmost_col != -999)
						{
						if (cols[rightmost_col][0].x > screenW - 30 || cols[leftmost_col][0].x < 30)
							{ 
								y_drop = 10
								ivader_dir = -ivader_dir 
							}
							else y_drop = 0
						}
						else
						{
							//ALL IVADERS KILLED
							trace("ALL IVADERS KILLED")
							resetVaders()
						}
					if (bottom_most > screenH - 60 && !cease_fire)
						{//Ivaders reached ground
							lives_left = 0
							if (tank.parent) tank.parent.removeChild(tank)
							cease_fire = true
							Tweener.addTween(this,{time:6,onComplete:restartTank})
						}
				}
				
			if (saucer_flying) renderSaucer()
				else 
				{
					if(Math.random()>0.99)launchSaucer()
				}
			if (leftFlag)
				{
					tank.x -= tank_speed
					checkBoundaries()
				}
			if (rightFlag)
				{
					tank.x += tank_speed
					checkBoundaries()
				}
			if (spaceFlag) fireBullet()
			
			canvas.graphics.clear()
			renderTankBullets()
			renderVaderBombs()
			renderScore()
		}
	
	private function updateIVaderCol(arr:Array):Boolean		
	{
			var last_vader:int = -1

			for (var i:int = 0; i < num_in_col;i++ )
				{
					arr[i].x += ivader_dir
					arr[i].y += y_drop
					if (arr[i].parent)
						{
							if (arr[i].bitmapData == vader1) arr[i].bitmapData = vader2
								else arr[i].bitmapData = vader1
							last_vader = i
							if(arr[i].y>bottom_most)bottom_most=arr[i].y
						}
				}
			if (Math.random() > bomb_ratio && last_vader > -1 && !cease_fire) dropBomb(new Point(arr[last_vader].x + 6, arr[last_vader].y + 10))
			
			return last_vader>-1 //true if column occupied
		}
		
	private function launchSaucer():void
		{
			saucer_flying=true
			if (Math.random() > 0.5)
				{
					saucer.x = screenW + 50
					saucer_speed=-Math.abs(saucer_speed)
				}
				else
				{
					saucer.x = -50
					saucer_speed=Math.abs(saucer_speed)
				}
			addChild(saucer)
		}
	private function renderSaucer():void
		{
			saucer.x += saucer_speed
			if (saucer.x > screenW + 50 || saucer.x < -50)
				{
					if(saucer.parent)removeChild(saucer)
					saucer_flying=false
				}
		}
	private function renderVaderBombs():void
		{
			var len:int = vader_bombs.length
			var remove:Array = []
			var i:int
			canvas.graphics.lineStyle(2, 0xFF0000)
			
			for (i = 0; i < len; i++)
				{
					vader_bombs[i].y += bullet_speed
					if (vader_bombs[i].y < screenH)	
						{
							if (this.getObjectsUnderPoint(vader_bombs[i])[0]==tank)
								{
									tankHitHandler()
									//bulletHitHandler(this.getObjectsUnderPoint(tank_bullets[i])[0])
									remove.push(i)
								}
							canvas.graphics.drawCircle(vader_bombs[i].x, vader_bombs[i].y, 1)
						}
						else remove.push(i)
				}
			//Remove bullets from array 
			if (remove.length > 0)
				{
					remove.sort(Array.NUMERIC)
					len = remove.length
					for (i = len-1; i >= 0; i--)
						{
							vader_bombs.splice(remove[i],1)
						}
				}
		}
	private function tankHitHandler():void
		{
			lives_left--
			tank.parent.removeChild(tank)
			cease_fire = true
			Tweener.addTween(this,{time:4,onComplete:restartTank})
		}
	private function restartTank():void
		{
			if (lives_left == 0)
				{
					lives_left = 3
					score = 0
					
					resetVaders()
					initParams()
				}
			cease_fire = false
			tank.x = screenW * 0.5
			addChild(tank)
		}
	private function dropBomb(posn:Point):void
		{
			if(vader_bombs.length<=max_bombs) vader_bombs.push(new Point(posn.x, posn.y))
		}
		
	private function renderTankBullets():void
		{
			var len:int = tank_bullets.length
			var remove:Array = []
			var i:int
			canvas.graphics.lineStyle(2, 0x00FF00)
			
			for (i = 0; i < len; i++)
				{
					tank_bullets[i].y -= bullet_speed
					if (tank_bullets[i].y > 0)	
						{
							if (this.getObjectsUnderPoint(tank_bullets[i]).length>0)
								{
									if(this.getObjectsUnderPoint(tank_bullets[i])[0].name.substr(0,6)=="ivader" )
										{
											bulletHitHandler(this.getObjectsUnderPoint(tank_bullets[i])[0])
											remove.push(i)
										}
								}
							canvas.graphics.drawRect(tank_bullets[i].x, tank_bullets[i].y, 1, 3)
						}
						else remove.push(i)
				}
			//Remove bullets from array 
			if (remove.length > 0)
				{
					remove.sort(Array.NUMERIC)
					len = remove.length
					for (i = len-1; i >=0; i--)
						{
							tank_bullets.splice(remove[i],1)
						}
				}
		}
		
	private function fireBullet():void
		{
			if(tank_bullets.length<=max_bullets && !cease_fire) tank_bullets.push(new Point(int(tank.x + tank.width * 0.5), tank.y-1))
			spaceFlag=false
		}
	private function bulletHitHandler(b:*):void
		{
			score += 100
			b.parent.removeChild(b)
            ivaders_down++
			var n:int = 2 + Math.floor(ivaders_down / (ivader_count * 0.25))
			ivader_dir = ivader_dir > 0?n: -n
			
			anim_speed=max_anim_speed-ivaders_down/(max_anim_speed-min_anim_speed)
			if (anim_speed<min_anim_speed)anim_speed=min_anim_speed
			trace("ivader_dir="+ivader_dir+"   leftmost="+leftmost_col+"  rightmost="+rightmost_col)
		}
	private function checkBoundaries():void
		{
			if (tank.x < 5) tank.x = 5
			else
			if(tank.x>screenW-tank.width-5)tank.x=screenW-tank.width-5
		}
		
	public function fig1():BitmapData
		{
            return BitmapPatternBuilder.build(
                [[0,0,1,0,0,0,0,0,1,0,0],
                 [0,0,0,1,0,0,0,1,0,0,0],
                 [0,0,1,1,1,1,1,1,1,0,0],
                 [0,1,1,0,1,1,1,0,1,1,0],
                 [1,1,1,1,1,1,1,1,1,1,1],
                 [1,0,1,1,1,1,1,1,1,0,1],
                 [1,0,1,0,0,0,0,0,1,0,1],
                 [0,0,0,1,1,0,1,1,0,0,0]],
                [0x00000000, 0xffCCCCCC]
            );
        }
		
    public function fig2():BitmapData
		{
            return BitmapPatternBuilder.build(
                [[0,0,1,0,0,0,0,0,1,0,0],
                 [1,0,0,1,0,0,0,1,0,0,1],
                 [1,0,1,1,1,1,1,1,1,0,1],
                 [1,1,1,0,1,1,1,0,1,1,1],
                 [1,1,1,1,1,1,1,1,1,1,1],
                 [0,1,1,1,1,1,1,1,1,1,0],
                 [0,0,1,0,0,0,0,0,1,0,0],
                 [0,1,0,0,0,0,0,0,0,1,0]],
                [0x00000000, 0xffCCCCCC]
            );
        }
		
	public function tankBmd():BitmapData
		{
            return BitmapPatternBuilder.build(
                [[0,0,0,0,0,0,0,0,0,0,0],
                 [0,0,0,0,0,0,0,0,0,0,0],
                 [0,0,0,0,0,1,0,0,0,0,0],
                 [0,0,0,0,1,1,1,0,0,0,0],
                 [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,0,0,0,0,0,1,1,1]],
                [0x00000000, 0xffAAAAAA]
            );
        }
		
	public function saucerBmd():BitmapData
		{
            return BitmapPatternBuilder.build(
                [[0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0],
                 [0,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0,0,0],
                 [0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0],
                 [0,0,0,0,1,1,1,1,0,1,1,0,1,1,1,1,0,0,0,0],
                 [1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1],
                 [0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
                 [0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0],
                 [0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0]],
                [0x00000000, 0xff990033]
            );
        }
		
/********************************************
* keyDownHandler - keyboard handler
*********************************************/   
        public function keyDownHandler(e:KeyboardEvent):void 
		{
			switch(e.keyCode)
			{//Set flags for key presses
				case Keyboard.LEFT:
					leftFlag = true;
					break;
				case Keyboard.RIGHT: 
					rightFlag = true;
					break;
				case Keyboard.SPACE:
                                case Keyboard.UP:
					spaceFlag = true;
					break;
				default:
			}
		}

/********************************************
* keyUpHandler - keyboard handler
*********************************************/ 		
		public function keyUpHandler(e:KeyboardEvent):void {
			switch(e.keyCode)
			{//Kill flags for the right key up
				case Keyboard.LEFT:
					leftFlag = false;
					break;
				case Keyboard.RIGHT: 
					rightFlag = false;
					break;
				case Keyboard.SPACE:
                                case Keyboard.UP:
					spaceFlag = false;
					break;
				default:
			}
		}
    }
}

/**-----------------------------------------------------
 * Use following BitmapPatternBuilder class 
 * 
 * DO NOT CHANGE any codes below this comment.
 *
 * -----------------------------------------------------
*/
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
    
class BitmapPatternBuilder{
    /**
     * creates BitmapData filled with dot pattern.
     * First parameter is 2d array that contains color index for each pixels;
     * Second parameter contains color reference table.
     *
     * @parameter pattern:Array 2d array that contains color index for each pixel.
     * @parameter colors:Array 1d array that contains color table.
     * @returns BitmapData
     */
    public static function build(pattern:Array, colors:Array):BitmapData{
        var bitmapW:int = pattern[0].length;
        var bitmapH:int = pattern.length;
        var bmd:BitmapData = new BitmapData(bitmapW,bitmapH,true,0x000000);
        for(var yy:int=0; yy<bitmapH; yy++){
            for(var xx:int=0; xx<bitmapW; xx++){
                var color:int = colors[pattern[yy][xx]];
                bmd.setPixel32(xx, yy, color);
            }
        }
        return bmd;
    }
    
    /**
     * short cut function for Graphics.beginBitmapFill with pattern.
     */
    public static function beginBitmapFill(pattern:Array, colors:Array, graphics:Graphics):void{
        var bmd:BitmapData = build(pattern, colors);
        graphics.beginBitmapFill(bmd);
        bmd.dispose();        
    }
}