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

Ponytail (何も考えずBraidをSTGにしてみた)

Braid (http://www.xbox.com/ja-JP/games/b/braidxboxlivearcade/)
が面白かったので何も考えずSTGにしてみた。
緑弾の扱いとか大失敗した感があるが後悔していない。
Get Adobe Flash player
by psyark 03 Jan 2009
// Braid (http://www.xbox.com/ja-JP/games/b/braidxboxlivearcade/)
// が面白かったので何も考えずSTGにしてみた。
// 緑弾の扱いとか大失敗した感があるが後悔していない。
package {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    
    import net.hires.debug.Stats;

    [SWF(width=465,height=465,frameRate=60,backgroundColor=0x111111)]
    public class Ponytail extends Sprite {
        private var step:uint = 0;
        private var step2:uint = 0;
        private var deadStep:uint = 0xFFFFFFFF;
        private var canvas:Canvas = new Canvas(400, 465);
        private var rewindHint:RewindHint = new RewindHint();
        private var fighter:Fighter = new Fighter(200, 420);
        private var waves:Array = [new Wave1(), new Wave2(), new Wave3()];
        private var waveIndex:uint = 0;
        private var bulletList:BulletList;
        
        /**
         * おコンストラクタ
         */
        public function Ponytail() {
            var bounds:Rectangle = canvas.bitmapData.rect.clone();
            bounds.inflate(4, 4);
            bulletList = new BulletList(bounds);
            
            addChild(canvas);
            
            var stats:Stats = new Stats();
            stats.x = canvas.width;
            addChild(stats);
            
            rewindHint.x = canvas.width - rewindHint.width >> 1;
            rewindHint.y = canvas.height - rewindHint.height >> 1;
            rewindHint.visible = false;
            addChild(rewindHint);
            
            addEventListener(Event.ENTER_FRAME, enterFrame);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyboardManager.keyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, KeyboardManager.keyUp);
        }
        
        /**
         * フレームごとの処理
         */
        private function enterFrame(event:Event):void {
            var i:uint;
            var forward:Boolean = false;
            
            if (KeyboardManager.keyStates[88]) {
                if (step > 0) {
                    step--;
                    canvas.rollback();
                } else {
                    canvas.clear();
                }
            } else if (step - deadStep > 30) {
                rewindHint.visible = true;
                return;
            } else {
                step++;
                canvas.clear();
                forward = true;
            }
            rewindHint.visible = false;
            step2++;
            
            if (forward) {
                canvas.sepia = Math.max(0, canvas.sepia - 0.02);
            } else {
                canvas.sepia = Math.min(1, canvas.sepia + 0.002);
            }
            
            var currentWave:IWave = waves[waveIndex % waves.length];
            currentWave.getBullets(step, step2, bulletList);
            
            if (deadStep > step) {
                if (forward) {
                    fighter.update(canvas.bitmapData.rect, step);
                    deadStep = 0xFFFFFFFF;
                    var hitRect:Rectangle = new Rectangle(fighter.getX(step) - 4, fighter.getY(step) - 4, 8, 8);
                    for (i=0; i<bulletList.count; i++) {
                        if (hitRect.contains(bulletList.listX[i], bulletList.listY[i])) {
                            deadStep = step;
                            break;
                        }
                    }
                }
                
                canvas.blit(fighter.bitmap, fighter.getX(step), fighter.getY(step));
            }
            
            for (i=0; i<bulletList.count; i++) {
                canvas.blit(
                    bulletList.listLocked[i] ? BulletVisual.locked : BulletVisual.normal,
                    bulletList.listX[i], bulletList.listY[i]
                );
            }
            
            if (step > 100 && deadStep > step && bulletList.count == 0) {
                fighter.reset(step);
                step = 0;
                step2 = 0;
                waveIndex++;
            }
        }
    }
}

import flash.display.BitmapData;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.display.Bitmap;
import flash.filters.ColorMatrixFilter;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;

class BulletList {
    private var bounds:Rectangle;
    public var listX:Vector.<Number> = new Vector.<Number>(0, false);
    public var listY:Vector.<Number> = new Vector.<Number>(0, false);
    public var listLocked:Vector.<Boolean> = new Vector.<Boolean>(0, false);
    public var count:uint = 0;
    
    public function BulletList(bounds:Rectangle) {
        this.bounds = bounds;
    }
    public function reset():void {
        count = 0;
    }
    public function addBullet(x:Number, y:Number, locked:Boolean=false):void {
        if (bounds.contains(x, y)) {
            listX[count] = x;
            listY[count] = y;
            listLocked[count] = locked;
            count++;
        }
    }
}

interface IWave {
    function getBullets(step1:uint, step2:uint, list:BulletList):void;
}
class Wave1 implements IWave {
    public function getBullets(step:uint, step2:uint, list:BulletList):void {
        list.reset();
        for (var i:uint=0; i<12; i++) {
            var elapsed:int = step - i * 12;
            if (elapsed > 0) {
                for (var j:uint=0; j<30; j++) {
                    var angle:Number = j / 30 * Math.PI * 2 - i * 0.021;
                    list.addBullet(Math.cos(angle) * elapsed + 200, Math.sin(angle) * elapsed + 100);
                }
            }
        }
    }
}
class Wave2 implements IWave {
    public function getBullets(step:uint, step2:uint, list:BulletList):void {
        list.reset();
        var elapsed:int;
        for (var i:uint=0; i<60; i++) {
            elapsed = step - i * 6;
            if (elapsed > 0) {
                for (var j:uint=0; j<10; j++) {
                    var angle:Number = j / 18 * Math.PI * 2;
                    list.addBullet(Math.cos(angle) * elapsed + 200, Math.sin(angle) * elapsed + 100);
                }
            }
        }
        elapsed = step - 59 * 6;
        if (elapsed > 0) {
            for (j=0; j<400 * 17 / 18; j++) {
                angle = (j / 400 + 8 / 18) * Math.PI * 2;
                list.addBullet(Math.cos(angle) * elapsed + 200, Math.sin(angle) * elapsed + 100);
            }
        }
    }
}
class Wave3 implements IWave {
    public function getBullets(step:uint, step2:uint, list:BulletList):void {
        list.reset();
        var elapsed:int;
        var i:uint, j:uint, angle:Number;
        for (i=0; i<60; i++) {
            elapsed = step - i * 8;
            if (elapsed > 0) {
                for (j=0; j<20; j++) {
                    angle = j / 20 * Math.PI * 2 + i * 0.02;
                    list.addBullet(Math.cos(angle) * elapsed + 180, Math.sin(angle) * elapsed + 100);
                }
            }
        }
        for (i=0; i<60; i++) {
            elapsed = step2 - i * 8;
            if (elapsed > 0) {
                for (j=0; j<20; j++) {
                    angle = j / 20 * Math.PI * 2 + i * -0.02;
                    list.addBullet(Math.cos(angle) * elapsed + 180, Math.sin(angle) * elapsed + 100, true);
                }
            }
        }
    }
}

class Fighter {
    private var historyX:Array;
    private var historyY:Array;
    public const bitmap:BitmapData = new BitmapData(16, 16, false, 0xFF0000);
    
    public function Fighter(x:Number, y:Number):void {
        historyX = [x];
        historyY = [y];
    }
    
    public function update(bounds:Rectangle, step:uint):void {
        var newX:Number = historyX[step - 1];
        var newY:Number = historyY[step - 1];
        
        if (KeyboardManager.keyStates[Keyboard.RIGHT]) {
            newX += 2;
        }
        if (KeyboardManager.keyStates[Keyboard.LEFT]) {
            newX -= 2;
        }
        if (KeyboardManager.keyStates[Keyboard.DOWN]) {
            newY += 2;
        }
        if (KeyboardManager.keyStates[Keyboard.UP]) {
            newY -= 2;
        }
        
        newX = Math.max(bounds.left, Math.min(bounds.right, newX));
        newY = Math.max(bounds.top, Math.min(bounds.bottom, newY));
        
        historyX[step] = newX;
        historyY[step] = newY;
    }
    
    public function getX(step:uint):Number {
        return historyX[step];
    }
    
    public function getY(step:uint):Number {
        return historyY[step];
    }
    
    public function reset(step:uint):void {
        historyX[0] = historyX[step];
        historyY[0] = historyY[step];
    }
}

class BulletVisual extends BitmapData {
    public static const normal:BulletVisual = new BulletVisual(0x0000FF, 0x00FFFF);
    public static const locked:BulletVisual = new BulletVisual(0x008000, 0x00FF00);
    public function BulletVisual(edgeColor:uint, frameColor:uint) {
        super(8, 8, false, edgeColor);
        fillRect(new Rectangle(1, 1, 6, 6), frameColor);
        fillRect(new Rectangle(2, 2, 4, 4), 0xFFFFFF);
    }
}

class Canvas extends Bitmap {
    private var bmp:BitmapData;
    private var tmp:BitmapData;
    private var darken:ColorTransform;
    private var shrink:Matrix;
    private var dest:Point = new Point();
    private var _sepia:Number = 0;
    private var rgb2yuv:ColorMatrixFilter = new ColorMatrixFilter([
        +0.299, +0.587, +0.114, 0, 0,
        -0.169, -0.331, +0.500, 0, 128,
        +0.500, -0.419, -0.081, 0, 128,
        0, 0, 0, 1, 0
    ]);
    private var yuv2rgb:ColorMatrixFilter = new ColorMatrixFilter([
        1, +0.000, +1.402, 0, 128 * -1.402,
        1, -0.344, -0.714, 0, 128 * (0.344 + 0.714),
        1, +1.772, +0.000, 0, 128 * -1.772,
        0, 0, 0, 1, 0
    ]);
    
    public function get sepia():Number {
        return _sepia;
    }
    public function set sepia(value:Number):void {
        if (_sepia != value) {
            _sepia = value;
            if (value) {
                var r:Number = 1 - value;
                var matrix:Array = rgb2yuv.matrix.slice();
                matrix[5]  *= r; matrix[6]  *= r; matrix[7]  *= r;
                matrix[10] *= r; matrix[11] *= r; matrix[12] *= r;
                matrix[9]  += value * -0.091 * 128;
                matrix[14] += value * +0.056 * 128;
                filters = [new ColorMatrixFilter(matrix), yuv2rgb];
            } else {
                filters = null;
            }
        }
    }
    
    public function Canvas(width:int, height:int):void {
        super(bmp = new BitmapData(width, height, false, 0));
        tmp = bmp.clone();
        darken = new ColorTransform(0.85, 0.85, 0.85);
        shrink = new Matrix();
        shrink.translate(width * -0.5, height * -0.5);
        shrink.scale(1.05, 1.05);
        shrink.translate(width * 0.5, height * 0.5);
    }
    public function clear():void {
        bmp.fillRect(bmp.rect, 0x000000);
    }
    public function rollback():void {
        tmp.copyPixels(bmp, bmp.rect, bmp.rect.topLeft);
        bmp.draw(tmp, shrink, darken);
    }
    public function blit(bitmap:BitmapData, x:Number, y:Number):void {
        dest.x = x - (bitmap.width >> 1);
        dest.y = y - (bitmap.height >> 1);
        bmp.copyPixels(bitmap, bitmap.rect, dest);
    }
}

class RewindHint extends TextField {
    public function RewindHint() {
        defaultTextFormat = new TextFormat("_typewriter", 30, 0xFFFFFF, true);
        text = "PRESS [X]";
        autoSize = TextFieldAutoSize.LEFT;
        selectable = false;
    }
}

class KeyboardManager {
    public static const keyStates:Object = {};
    public static function keyDown(event:KeyboardEvent):void {
        keyStates[event.keyCode] = true;
    }
    public static function keyUp(event:KeyboardEvent):void {
        keyStates[event.keyCode] = false;
    }
}