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
/**
* 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();
}
}