// forked from ABA's forked from: forked from: AAShip // forked from ABA's forked from: AAShip // forked from ABA's AAShip // AAShip.as // Ascii art ship. // [Control] // Movement: Arrow or [WASD] keys. // Fire: [Z], [X], [.] or [/] key. package { import flash.display.Sprite; import flash.display.BitmapData; import flash.display.Bitmap; import flash.geom.Rectangle; import flash.text.TextField; import flash.events.Event; import flash.events.KeyboardEvent; [SWF(width="465", height="465", backgroundColor="0x000000", frameRate="30")] public class AAShip extends Sprite { public static const SCREEN_WIDTH:int = 465; public static const SCREEN_HEIGHT:int = 465; private const BLUR_MAX_COUNT:int = 512; private const BLUR_HISTORY_COUNT:int = 6; private const SHIP_SPEED:Number = 8; private const SHOT_MAX_COUNT:int = 12; private const SHOT_SPEED:Number = 20; private const SHIP_COLLISION_SIZE:Number = 5; private const SHIP_INVINCIBLE_TICKS:int = 90; private const ENEMY_MAX_COUNT:int = 16; private const BULLET_MAX_COUNT:int = 128; private const SPARK_MAX_COUNT:int = 64; private const ZAKO1_APPEARANCE_INTERVAL:Number = 30; private const MID1_APPEARANCE_INTERVAL:Number = 180; public static var gameSpeed:Number; private var buffer:BitmapData = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0); private var rect:Rectangle = new Rectangle; private var offset:Vector2 = new Vector2; private var blurs:Vector.<Vector.<Blur>> = new Vector.<Vector.<Blur>>(BLUR_HISTORY_COUNT, true); private var blurCounts:Vector.<int> = new Vector.<int>(BLUR_HISTORY_COUNT, true); private var blurIndex:int; private var shipChar:AAChar; private var shipSprite:Sprite = new Sprite; private var shipPos:Vector2 = new Vector2; private var shipAngle:Number; private var shipInvincibleTicks:int; private var shipFireCount:int; private var shipFireTicks:Number; private var shotChar:AAChar; private var shots:Vector.<Shot> = new Vector.<Shot>(SHOT_MAX_COUNT, true); private var enemies:Vector.<Enemy> = new Vector.<Enemy>(ENEMY_MAX_COUNT, true); private var zako1:Zako1, mid1:Mid1; private var bulletChar:AAChar; private var bullets:Vector.<Bullet> = new Vector.<Bullet>(BULLET_MAX_COUNT, true); private var sparkChar:AAChar; private var sparks:Vector.<Spark> = new Vector.<Spark>(SPARK_MAX_COUNT, true); private var bulletIntervalRank:Number; private var bulletSpeedRank:Number; private var enemyIntervalRank:Number; private var enemySpeedRank:Number; private var rankTicks:int; public function AAShip() { stage.scaleMode = "noScale"; addChild(new Bitmap(buffer)); stage.addEventListener(KeyboardEvent.KEY_DOWN, Key.onKeyDown); stage.addEventListener(KeyboardEvent.KEY_UP, Key.onKeyUp); AAChar.initialize(); Field.initialize(); var i:int; for (i = 0; i < BLUR_HISTORY_COUNT; i++) { var bs:Vector.<Blur> = new Vector.<Blur>(BLUR_MAX_COUNT, true); for (var j:int = 0; j < BLUR_MAX_COUNT; j++) { bs[j] = new Blur; } blurs[i] = bs; blurCounts[i] = 0; } blurIndex = 0; shipChar = new AAChar([" A ", "I#I"], [" R ", "CBC"], 2, 2); shipChar.drawToSprite(shipSprite); shipInvincibleTicks = -SHIP_INVINCIBLE_TICKS; shotChar = new AAChar(["!"], ["Y"]); for (i = 0; i < SHOT_MAX_COUNT; i++) { shots[i] = new Shot; shotChar.drawToSprite(shots[i].sprite); } zako1 = new Zako1; mid1 = new Mid1; for (i = 0; i < ENEMY_MAX_COUNT; i++) { enemies[i] = new Enemy; } bulletChar = new AAChar(["#"], ["P"], 1, 1); for (i = 0; i < BULLET_MAX_COUNT; i++) { bullets[i] = new Bullet; bulletChar.drawToSprite(bullets[i].sprite); } sparkChar = new AAChar(["*"], ["Y"]); for (i = 0; i < SPARK_MAX_COUNT; i++) { sparks[i] = new Spark; sparkChar.drawToSprite(sparks[i].sprite); } bulletIntervalRank = bulletSpeedRank = enemyIntervalRank = enemySpeedRank = 1.0 / 0.5; gameSpeed = 1.0; addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function initializeShip():void { shipPos.x = 0; shipPos.y = Field.size.y / 2; shipAngle = 0.0; shipFireCount = 0; shipFireTicks = 0; bulletIntervalRank *= 0.5; bulletSpeedRank *= 0.5; enemyIntervalRank *= 0.5; enemySpeedRank *= 0.5; if (bulletIntervalRank < 0.5) bulletIntervalRank = 0.5; if (bulletSpeedRank < 0.5) bulletSpeedRank = 0.5; if (enemyIntervalRank < 0.5) enemyIntervalRank = 0.5; if (enemySpeedRank < 0.5) enemySpeedRank = 0.5; rankTicks = 0; zako1.appearanceTicks = 0; mid1.appearanceTicks = MID1_APPEARANCE_INTERVAL; shipChar.setSpriteMatrix(shipSprite, shipPos, shipAngle); addChild(shipSprite); } private function onEnterFrame(event:Event):void { buffer.fillRect(buffer.rect, 0); var i:int; blurCounts[blurIndex] = 0; updateSparks(); updateShots(); if (shipInvincibleTicks > -SHIP_INVINCIBLE_TICKS) updateShip(); else if (shipInvincibleTicks == -SHIP_INVINCIBLE_TICKS) initializeShip(); else Field.offsetX *= 0.95; shipInvincibleTicks++; updateEnemies(); updateBullets(); rankTicks++; bulletIntervalRank += 0.02; if (rankTicks % (10 * 30) == 0) bulletIntervalRank *= 0.5; bulletSpeedRank += 0.005; if (rankTicks % (15 * 30) == 0) bulletSpeedRank *= 0.5; enemyIntervalRank += 0.005; if (rankTicks % (21 * 30) == 0) enemyIntervalRank *= 0.5; enemySpeedRank += 0.002; if (rankTicks % (27 * 30) == 0) enemySpeedRank *= 0.5; buffer.lock(); Field.draw(buffer); var bi:int = blurIndex + 1; for (i = 0; i < BLUR_HISTORY_COUNT; i++) { if (bi >= BLUR_HISTORY_COUNT) bi = 0; for (var j:int = 0; j < blurCounts[bi]; j++) { updateBlur(blurs[bi][j]); } bi++; } Field.drawSideBoard(buffer); buffer.unlock(); blurIndex++; if (blurIndex >= BLUR_HISTORY_COUNT) blurIndex = 0; } private function updateShip():void { var px:Number = shipPos.x; var vx:Number = 0, vy:Number = 0; if (Key.left) vx = -1; if (Key.right) vx = 1; if (Key.up) vy = -1; if (Key.down) vy = 1; if (vx != 0 && vy != 0) { vx *= 0.7; vy *= 0.7; } shipPos.x += vx * SHIP_SPEED * gameSpeed; shipPos.y += vy * SHIP_SPEED * gameSpeed; if (shipPos.x < -SCREEN_WIDTH / 2) shipPos.x = -SCREEN_WIDTH / 2; if (shipPos.x > SCREEN_WIDTH / 2) shipPos.x = SCREEN_WIDTH / 2; if (shipPos.y < -SCREEN_HEIGHT / 2) shipPos.y = -SCREEN_HEIGHT / 2; if (shipPos.y > SCREEN_HEIGHT / 2) shipPos.y = SCREEN_HEIGHT / 2; shipAngle += (shipPos.x - px) * 0.01; shipAngle *= 0.8; Field.offsetX = shipPos.x * 0.33; shipChar.setSpriteMatrix(shipSprite, shipPos, shipAngle); if (shipInvincibleTicks >= 0 || (-shipInvincibleTicks % 15 > 7)) { addBlursOfAAChar(shipChar, shipPos, shipAngle); } var s:Shot; if (Key.button1 && shipFireTicks <= 0) { shipFireTicks += 1.0; offset.x = 15; offset.y = 0; offset.rotation(shipAngle); s = getActorInstance(Vector.<Actor>(shots)); var i:int = shipFireCount % 2; if (s != null) { s.pos.x = shipPos.x + offset.x * (i * 2 - 1); s.pos.y = shipPos.y + offset.y * (i * 2 - 1); s.angle = shipAngle; s.ticks = 0; addBlur(s.pos.x, s.pos.y, 10, 10, 255, 255, 0); shotChar.setSpriteMatrix(s.sprite, s.pos, s.angle); addChild(s.sprite); shipFireCount++; } } shipFireTicks -= gameSpeed; if (shipInvincibleTicks >= 0) { for each (var e:Enemy in enemies) { if (!e.exists) continue; if (Math.abs(shipPos.x - e.pos.x) <= e.spec.size.x - 12 && Math.abs(shipPos.y - e.pos.y) <= e.spec.size.y - 12) { shipDestroyed(); e.exists = false; removeChild(e.sprite); return; } } for each (var b:Bullet in bullets) { if (!b.exists) continue; if (shipPos.getRoughDistance(b.pos) <= SHIP_COLLISION_SIZE) { shipDestroyed(); b.exists = false; removeChild(b.sprite); return; } } } } private function updateShots():void { var s:Shot; for each (s in shots) { if (!s.exists) continue; s.pos.x += Math.sin(s.angle) * SHOT_SPEED * gameSpeed; s.pos.y -= Math.cos(s.angle) * SHOT_SPEED * gameSpeed; if (s.pos.y < -SCREEN_HEIGHT / 2) { s.exists = false; removeChild(s.sprite); continue; } s.ticks += gameSpeed; shotChar.setSpriteMatrix(s.sprite, s.pos, s.angle); addBlursOfAAChar(shotChar, s.pos, s.angle, 1.0, 1.0, 150, 100, 0); for each (var e:Enemy in enemies) { if (!e.exists) continue; if (Math.abs(s.pos.x - e.pos.x) <= e.spec.size.x && Math.abs(s.pos.y - e.pos.y) <= e.spec.size.y) { addSpark(s.pos, s.angle + Math.PI, 0.2, SHOT_SPEED, 1.0, 2); e.shield--; e.isHit = true; s.exists = false; removeChild(s.sprite); break; } } } } private function updateEnemies():void { var e:Enemy; var es:EnemySpec = null; zako1.appearanceTicks -= gameSpeed; if (zako1.appearanceTicks <= 0) { es = zako1; var ei:int = ZAKO1_APPEARANCE_INTERVAL / enemyIntervalRank; ei *= (0.75 + Math.random() * 0.5); if (ei < 5) ei = 5; zako1.appearanceTicks += ei; } mid1.appearanceTicks -= gameSpeed; if (mid1.appearanceTicks <= 0) { es = mid1; mid1.appearanceTicks += MID1_APPEARANCE_INTERVAL * (0.5 + Math.random()); } if (es != null) { e = getActorInstance(Vector.<Actor>(enemies)); if (e != null) { e.spec = es; e.speedRatio = enemySpeedRank; var fsr:Number = bulletSpeedRank; if (fsr < 1.0) fsr = 1.0; e.fireSpeedRatio = fsr; var fir:Number = bulletIntervalRank; if (fir > 25.0) fir = 25.0; e.fireIntervalRatio = fir; e.ticks = 0; e.fireTicks = 0.0; e.fireSeqTicks = 0.0; e.fireCount = 0; e.shield = e.spec.shield; e.isHit = false; e.spec.initialize(e, shipPos); e.spec.aaChar.drawToSprite(e.sprite); addChild(e.sprite); } } for each (e in enemies) { if (!e.exists) continue; if (!Field.contains(e.pos) || e.shield <= 0) { e.exists = false; removeChild(e.sprite); if (e.shield <= 0) addSpark(e.pos, 0, Math.PI, 4.0, 1.5, 8); continue; } e.spec.update(e, shipPos, this); e.ticks += gameSpeed; e.fireTicks -= gameSpeed; e.spec.aaChar.setSpriteMatrix(e.sprite, e.pos, e.angle, e.spec.scale.x, e.spec.scale.y); if (e.isHit) { e.isHit = false; addBlursOfAAChar(e.spec.aaChar, e.pos, e.angle, e.spec.scale.x * 1.5, e.spec.scale.y * 1.5, 255, 255, 0); } else { addBlursOfAAChar(e.spec.aaChar, e.pos, e.angle, e.spec.scale.x, e.spec.scale.y); } } } public function fireBullet(p:Vector2, angle:Number, speed:Number, size:Number):void { if (p.getRoughDistance(shipPos) <= 200 || p.x - Field.offsetX <= -Field.size.x + Field.SIDE_BOARD_WIDTH || p.x - Field.offsetX >= Field.size.x - Field.SIDE_BOARD_WIDTH) return; var b:Bullet = getActorInstance(Vector.<Actor>(bullets)); if (b == null) return; b.pos.x = p.x; b.pos.y = p.y; b.vel.x = Math.sin(angle) * speed; b.vel.y = -Math.cos(angle) * speed; b.speed = speed; b.size = size; addBlur(b.pos.x + b.vel.x * 2, b.pos.y + b.vel.y * 2, 20, 20, 255, 200, 100); b.ticks = 0; addChild(b.sprite); } private function updateBullets():void { var totalSpeed:Number = 0; for each (var b:Bullet in bullets) { if (!b.exists) continue; b.pos.addMultiplied(b.vel, gameSpeed); if (!Field.contains(b.pos)) { b.exists = false; removeChild(b.sprite); continue; } var a:Number = b.ticks * 0.1; bulletChar.setSpriteMatrix(b.sprite, b.pos, a, b.size, b.size); var sz:Number = b.size * (1.1 + Math.sin(b.ticks * 0.2) * 0.2); var cl:int = 128 + 64 + Math.sin(b.ticks * 0.3) * 64; addBlursOfAAChar(bulletChar, b.pos, a, sz, sz, cl, 100, 255); b.ticks += gameSpeed; totalSpeed += b.speed + 5.0; } if (totalSpeed > 500.0) { gameSpeed = 1.0 - (totalSpeed - 500.0) / 250.0; if (gameSpeed < 0.7) gameSpeed = 0.7; } else { gameSpeed = 1.0; } } private function updateSparks():void { for each (var s:Spark in sparks) { if (!s.exists) continue; s.pos.addMultiplied(s.vel, gameSpeed); s.vel.mul(1 - 0.05 * gameSpeed); s.size *= (1 - 0.05 * gameSpeed); if (!Field.contains(s.pos) || s.ticks <= 0) { s.exists = false; removeChild(s.sprite); continue; } var a:Number = s.ticks * 0.2; sparkChar.setSpriteMatrix(s.sprite, s.pos, a, s.size, s.size); addBlursOfAAChar(sparkChar, s.pos, a, s.size, s.size, 250, Math.random() * 128 + 128, 0); s.ticks -= gameSpeed; } } private function shipDestroyed():void { addSpark(shipPos, 0, Math.PI, 10.0, 6.0, 20); addSpark(shipPos, Math.PI / 2, 0, 30.0, 5.0, 10); addSpark(shipPos, -Math.PI / 2, 0, 30.0, 5.0, 10); shipInvincibleTicks = -SHIP_INVINCIBLE_TICKS * 1.5; removeChild(shipSprite); } private function addSpark(p:Vector2, angle:Number, ao:Number, speed:Number, size:Number, count:Number):void { for (var i:int = 0; i < count; i++) { var s:Spark = getActorInstance(Vector.<Actor>(sparks)); if (s == null) return; s.pos.x = p.x; s.pos.y = p.y; var a:Number = angle + ao * (Math.random() * 2 - 1); var sp:Number = speed * (0.5 + Math.random()); s.vel.x = Math.sin(a) * sp; s.vel.y = -Math.cos(a) * sp; s.size = size; s.ticks = 15 + 15 * Math.random(); sparkChar.setSpriteMatrix(s.sprite, s.pos, a, s.size, s.size); addChild(s.sprite); } } private function addBlursOfAAChar(ac:AAChar, p:Vector2, angle:Number, sx:Number = 1, sy:Number = 1, cr:int = -1, cg:int = -1, cb:int = -1):void { var br:int, bg:int, bb:int; if (cr >= 0) { br = cr; bg = cg; bb = cb; } for each (var b:Blur in ac.blurs) { offset.x = b.pos.x * sx; offset.y = b.pos.y * sy; offset.rotation(angle); if (cr < 0) { br = b.r; bg = b.g; bb = b.b; } addBlur(p.x + offset.x, p.y + offset.y, b.width * sx, b.height * sy, br, bg, bb); } } private function addBlur(x:Number, y:Number, w:Number, h:Number, r:int, g:int, b:int):void { if (blurCounts[blurIndex] >= BLUR_MAX_COUNT) return; var bl:Blur = blurs[blurIndex][blurCounts[blurIndex]]; bl.pos.x = x + SCREEN_WIDTH / 2; bl.pos.y = y + SCREEN_HEIGHT / 2; bl.width = w; bl.height = h; bl.r = r; bl.g = g; bl.b = b; blurCounts[blurIndex]++; } private function updateBlur(b:Blur):void { rect.x = b.pos.x - b.width / 2 - Field.offsetX; rect.y = b.pos.y - b.height / 2; rect.width = b.width; rect.height = b.height; buffer.fillRect(rect, b.r * 0x10000 + b.g * 0x100 + b.b); b.width *= 1.2; b.height *= 1.2; var a:int = (b.r + b.g + b.b) / 3; b.r += (a - b.r) * 0.25; b.g += (a - b.g) * 0.25; b.b += (a - b.b) * 0.25; b.r *= 0.65; b.g *= 0.65; b.b *= 0.65; } private function getActorInstance(actors:Vector.<Actor>):* { var al:int = actors.length for (var i:int = 0; i < al; i++) { if (!actors[i].exists) { actors[i].exists = true; return actors[i]; } } return null; } } } import flash.display.BitmapData; import flash.display.Bitmap; import flash.display.Sprite; import flash.geom.Rectangle; import flash.geom.Matrix; import flash.text.TextField; import flash.text.TextFormat; import flash.events.KeyboardEvent; class Actor { public var exists:Boolean = false; public var pos:Vector2 = new Vector2; public var sprite:Sprite = new Sprite; public var ticks:Number; } class Shot extends Actor { public var angle:Number; } class Enemy extends Actor { public var angle:Number; public var speed:Number; public var speedRatio:Number; public var fireSpeedRatio:Number; public var fireIntervalRatio:Number; public var fireTicks:Number; public var fireSeqTicks:Number; public var fireCount:int; public var shield:int; public var isHit:Boolean; public var spec:EnemySpec; } class EnemySpec { public var size:Vector2 = new Vector2; public var scale:Vector2 = new Vector2; public var shield:int; public var aaChar:AAChar; public var appearanceTicks:Number; public function initialize(e:Enemy, shipPos:Vector2):void { } public function update(e:Enemy, shipPos:Vector2, main:AAShip):void {} } class Zako1 extends EnemySpec { private const SPEED:Number = 6; private const ANGLE_VELOCITY:Number = 0.05; private const FIRE_INTERVAL:Number = 60; private const BULLET_SPEED:Number = 5; public function Zako1() { size.x = size.y = 32; scale.x = scale.y = 1.0; shield = 1; aaChar = new AAChar(["<O>", " v "], ["WGW", " C "], 2, 2); } override public function initialize(e:Enemy, shipPos:Vector2):void { e.pos.x = Field.size.x * (Math.random() * 2 - 1); e.pos.y = -Field.size.y; e.angle = Math.PI; e.speed = SPEED * e.speedRatio; } override public function update(e:Enemy, shipPos:Vector2, main:AAShip):void { e.pos.x += Math.sin(e.angle) * e.speed * AAShip.gameSpeed; e.pos.y -= Math.cos(e.angle) * e.speed * AAShip.gameSpeed; var pa:Number = Math.atan2(-e.pos.x + shipPos.x, e.pos.y - shipPos.y); var ao:Number = pa - e.angle; ao = Util.normalizeAngle(ao); if (ao > ANGLE_VELOCITY) e.angle += ANGLE_VELOCITY; else if (ao < -ANGLE_VELOCITY) e.angle -= ANGLE_VELOCITY; else e.angle = pa; e.angle = Util.normalizeAngle(e.angle); if (e.fireTicks <= 0) { e.fireTicks += FIRE_INTERVAL / e.fireIntervalRatio; main.fireBullet(e.pos, pa, BULLET_SPEED * e.fireSpeedRatio, 1.0); } } } class Mid1 extends EnemySpec { private const WAVE_INTERVAL:int = 120; private const SPEED:Number = 1; private const FIRE_INTERVAL:Number = 150; private const BULLET_SPEED:Number = 5; public function Mid1() { size.x = 64; size.y = 48; scale.x = scale.y = 1.2; shield = 16; aaChar = new AAChar([".__.", "\\##/"], ["RYYR", "WCCW"], 2, 2); } override public function initialize(e:Enemy, shipPos:Vector2):void { e.pos.x = Field.size.x * 0.6 * (Math.random() * 2 - 1); e.ticks = Math.random() * WAVE_INTERVAL; e.pos.y = -Field.size.y; e.angle = 0; e.speed = SPEED * (Math.random() + 1.0); e.fireSpeedRatio = Math.sqrt(e.fireSpeedRatio); e.fireIntervalRatio = Math.sqrt(e.fireIntervalRatio); } override public function update(e:Enemy, shipPos:Vector2, main:AAShip):void { var xa:Number = e.ticks * Math.PI * 2.0 / WAVE_INTERVAL; e.pos.x += Math.sin(xa) * 1.0 * AAShip.gameSpeed; e.angle = -Math.sin(xa) * 0.2; e.pos.y += e.speed * AAShip.gameSpeed; if (e.pos.y < 0) { if (e.fireTicks <= 0) { e.fireTicks += FIRE_INTERVAL / e.fireIntervalRatio; e.fireSeqTicks = 0; e.fireCount = 4; } if (e.fireCount > 0) { e.fireSeqTicks -= AAShip.gameSpeed; if (e.fireSeqTicks <= 0) { e.fireSeqTicks = 3; e.fireCount--; var pa:Number = Math.atan2(-e.pos.x + shipPos.x, e.pos.y - shipPos.y); for (var i:int = 0; i < 3; i++) { main.fireBullet(e.pos, pa - (i - 1) * 0.5, BULLET_SPEED * e.fireSpeedRatio * (1.0 + (3 - e.fireCount) * 0.25), 1.25); } } } } else { e.speed += (SPEED * 4 - e.speed) * 0.1; } } } class Bullet extends Actor { public var vel:Vector2 = new Vector2; public var speed:Number; public var size:Number; } class Spark extends Actor { public var vel:Vector2 = new Vector2; public var size:Number; } class Blur { public var pos:Vector2 = new Vector2; public var width:Number, height:Number; public var r:int, g:int, b:int; } class Field { public static const SIDE_BOARD_WIDTH:Number = AAShip.SCREEN_WIDTH / 6; private static const STAR_COUNT:int = 256; public static var size:Vector2; public static var offsetX:Number; private static var stars:Vector.<Star>; private static var rect:Rectangle = new Rectangle; public static function initialize():void { size = new Vector2; size.x = AAShip.SCREEN_WIDTH * 1.1 / 2; size.y = AAShip.SCREEN_HEIGHT * 1.1 / 2; stars = new Vector.<Star>(STAR_COUNT, true); for (var i:int = 0; i < STAR_COUNT; i++) { var s:Star = new Star; var z:Number = 1.0 + Math.random() * 10; var sz:int = (5 + Math.random() * 5) / z; if (sz < 1) sz = 1; s.pos.x = (Math.random() * 2 - 1) * size.x - sz; s.pos.y = (Math.random() * 2 - 1) * size.y - sz; s.size = sz; s.velRatio = 1.0 / z; s.color = (int)(Math.random() * 127 + 128) * 0x100 + (int)(Math.random() * 127 + 128); stars[i] = s; } } public static function draw(buffer:BitmapData):void { for each (var s:Star in stars) { rect.x = s.pos.x - offsetX * s.velRatio + AAShip.SCREEN_WIDTH / 2; rect.y = s.pos.y + AAShip.SCREEN_HEIGHT / 2; rect.width = rect.height = s.size; buffer.fillRect(rect, s.color); s.pos.y += 3.0 * s.velRatio; if (s.pos.y > size.y) s.pos.y -= size.y * 2; } } public static function drawSideBoard(buffer:BitmapData):void { rect.width = SIDE_BOARD_WIDTH; rect.height = AAShip.SCREEN_HEIGHT; rect.x = rect.y = 0; buffer.fillRect(rect, 0); rect.x = AAShip.SCREEN_WIDTH - rect.width; buffer.fillRect(rect, 0); } public static function contains(p:Vector2):Boolean { return (p.x >= -size.x && p.x <= size.x && p.y >= -size.y && p.y <= size.y); } } class Star { public var pos:Vector2 = new Vector2; public var size:Number; public var color:int; public var velRatio:Number; } class AAChar { private static const COLOR_PATTERNS:Array = [["R", 250, 100, 100], ["G", 100, 250, 100], ["B", 100, 100, 250], ["Y", 250, 250, 100], ["P", 250, 100, 250], ["C", 100, 250, 250], ["W", 250, 250, 250]]; private const CHAR_SIZE:int = 24; private const CHAR_OFFSET_X:int = 14; private const CHAR_OFFSET_Y:int = 17; private const CHAR_HEIGHT:int = 24; private static var colorCount:int; private static var textFormats:Vector.<TextFormat> = new Vector.<TextFormat>; public var textFields:Vector.<TextField> = new Vector.<TextField>; public var blurs:Vector.<Blur> = new Vector.<Blur>; public var width:int, height:int; private var bitmapData:BitmapData; public static function initialize():void { colorCount = 0; for each (var cp:Array in COLOR_PATTERNS) { var tf:TextFormat = new TextFormat; tf.font = "_typewriter"; tf.bold = true; tf.size = 24; tf.leading = -10; tf.color = (int)(cp[1] * 0.75) * 0x10000 + (int)(cp[2] * 0.75) * 0x100 + (int)(cp[3] * 0.75); textFormats.push(tf); colorCount++; } } public function AAChar(chars:Array, colors:Array, divX:int = 1, divY:int = 1) { var i:int; var tfts:Vector.<String> = new Vector.<String>(colorCount, true); var tffs:Vector.<Boolean> = new Vector.<Boolean>(colorCount, true); for (i = 0; i < colorCount; i++) { tfts[i] = ""; tffs[i] = false; } var cx:int, cy:int = 0; var bd:BitmapData; var tf:TextField; var b:Blur; for (i = 0; i < chars.length; i++) { var str:String = chars[i]; var colorStr:String = colors[i]; cx = 0; var j:int; for (j = 0; j < str.length; j++) { var c:String = str.charAt(j); var color:String = colorStr.charAt(j); var ci:int; for (var k:int = 0; k < colorCount; k++) { if (color == COLOR_PATTERNS[k][0]) { tfts[k] += c; tffs[k] = true; ci = k; } else { tfts[k] += " "; } } bd = new BitmapData(CHAR_SIZE, CHAR_SIZE, false, 0); tf = new TextField; tf.defaultTextFormat = textFormats[ci]; tf.text = c; bd.draw(tf); for (var dx:int = 0; dx < divX; dx++) { for (var dy:int = 0; dy < divY; dy++) { var minX:int = CHAR_SIZE, maxX:int = -1; var minY:int = CHAR_SIZE, maxY:int = -1; for (var x:int = dx * CHAR_SIZE / divX; x < (dx + 1) * CHAR_SIZE / divX; x++) { for (var y:int = dy * CHAR_SIZE / divY; y < (dy + 1) * CHAR_SIZE / divY; y++) { if (bd.getPixel(x, y) > 0) { if (minX > x) minX = x; if (maxX < x) maxX = x; if (minY > y) minY = y; if (maxY < y) maxY = y; } } } if (maxX >= 0) { b = new Blur; b.width = maxX - minX + 1; b.height = maxY - minY + 1; b.pos.x = minX + cx * CHAR_OFFSET_X + b.width / 2; b.pos.y = minY + cy * CHAR_OFFSET_Y + b.height / 2; b.r = COLOR_PATTERNS[ci][1] + (255 - COLOR_PATTERNS[ci][1]) * 0.5; b.g = COLOR_PATTERNS[ci][2] + (255 - COLOR_PATTERNS[ci][2]) * 0.5; b.b = COLOR_PATTERNS[ci][3] + (255 - COLOR_PATTERNS[ci][3]) * 0.5; blurs.push(b); } } } cx++; } for (j = 0; j < colorCount; j++) { tfts[j] += "\n"; } cy++; } width = cx * CHAR_OFFSET_X; height = cy * CHAR_HEIGHT; for (i = 0; i < colorCount; i++) { if (!tffs[i]) continue; tf = new TextField; tf.defaultTextFormat = textFormats[i]; tf.multiline = true; tf.text = tfts[i]; textFields.push(tf); } for each (b in blurs) { b.pos.x -= width / 2; b.pos.y -= height / 2; } bitmapData = new BitmapData(width, height, true, 0); for each (tf in textFields) { bitmapData.draw(tf); } } public function drawToSprite(s:Sprite):void { while (s.numChildren > 0) { s.removeChildAt(0); } s.addChild(new Bitmap(bitmapData)); } public function setSpriteMatrix(s:Sprite, p:Vector2, angle:Number, sx:Number = 1, sy:Number = 1):void { var m:Matrix = new Matrix; m.translate(-width / 2, -height / 2); m.scale(sx, sy); m.rotate(angle); m.translate(p.x + AAShip.SCREEN_WIDTH / 2 - Field.offsetX, p.y + AAShip.SCREEN_HEIGHT / 2); s.transform.matrix = m; } } // Utility classes. class Vector2 { public var x:Number = 0; public var y:Number = 0; public function add(v:Vector2):void { x += v.x; y += v.y; } public function addMultiplied(v:Vector2, mv:Number):void { x += v.x * mv; y += v.y * mv; } public function sub(v:Vector2):void { x -= v.x; y -= v.y; } public function mul(v:Number):void { x *= v; y *= v; } public function div(v:Number):void { x /= v; y /= v; } public function normalize():void { div(length); } public function get length():Number { return Math.sqrt(x * x + y * y); } public function getRoughDistance(p:Vector2):Number { return Math.abs(x - p.x) + Math.abs(y - p.y); } public function rotation(v:Number):void { var sv:Number = Math.sin(v); var cv:Number = Math.cos(v); var rx:Number = cv * x - sv * y; y = sv * x + cv * y; x = rx; } } class Key { public static var left:Boolean, up:Boolean, right:Boolean, down:Boolean; public static var button1:Boolean; public static function onKeyUp(event:KeyboardEvent):void { switch (event.keyCode) { case 0x25: case 0x41: { left = false; break; } case 0x26: case 0x57: { up = false; break; } case 0x27: case 0x44: { right = false; break; } case 0x28: case 0x53: { down = false; break; } case 0x5a: case 0xbf: case 0x58: case 0xbe: { button1 = false; break; } } } public static function onKeyDown(event:KeyboardEvent):void { switch (event.keyCode) { case 0x25: case 0x41: { left = true; break; } case 0x26: case 0x57: { up = true; break; } case 0x27: case 0x44: { right = true; break; } case 0x28: case 0x53: { down = true; break; } case 0x5a: case 0xbf: case 0x58: case 0xbe: { button1 = true; break; } } } } class Util { public static function normalizeAngle(v:Number):Number { if (v > Math.PI) return v - Math.PI * 2; else if (v < -Math.PI) return v + Math.PI * 2; else return v; } } forked from: forked from: forked from: AAShip