Beautifl - Flash Gallery

Thumbnail : Landolt Wars
Landolt Wars
k0rin 2012-03-21 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

package
{
    import flash.display.*;
    import flash.events.*;
    import org.libspark.betweenas3.*;
    
    [SWF(width = "465", height = "465", frameRate = "60")]
    public class Main extends Sprite
    {
        public var score:Score = new Score();
        public var board:Board;
        
        public function Main()
        {
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }
        
        private function enterFrameHandler(e:Event):void 
        {
            if (stage.stageWidth > 0) {
                removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
                start();
            }
        }
        
        public function start():void
        {
            board = new Board();
            addChild(board);
            
            score.x = 25;
            score.y = 20;
            addChild(score);
            
            startTitle();
        }
        
        public function startTitle():void
        {
            //Helper.traceDisplayList(this);
            
            var gameField:GameField = getChildByName("GameField") as GameField;
            if (gameField) {
                BetweenAS3.serial(
                    BetweenAS3.to(gameField, { alpha: 0 }, 0.3),
                    BetweenAS3.func(function ():void { gameField.destroy(); } )
                ).play();
            }
            
            board.turnOff();
            addChild(new TitlePanel());
        }
        
        public function startGame():void
        {
            board.turnOn();
            
            score.reset();
            addChildAt(new GameField(), 1);
        }
    }
}

import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.text.*;
import org.libspark.betweenas3.*;
import org.libspark.betweenas3.easing.*;

class GameSprite extends Sprite
{
    private var active:Boolean = true;
    private var frame:Number = 0;
    
    public function GameSprite()
    {
        if (stage) {
            start();
        } else {
            addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }
    }
    
    private function addedToStageHandler(e:Event):void 
    {
        removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        start();
        
        addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
        addEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }
    
    private function removedFromStage(e:Event):void 
    {
        removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
        
        onDestroy();
        removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }
    
    private function enterFrameHandler(e:Event):void 
    {
        if (active) {
            frame++;
            update();
        }
    }
    
    public final function destroy():void
    {
        parent.removeChild(this);
    }
    
    public final function getFrame():Number
    {
        return frame;
    }
    
    public final function setActive(active:Boolean):void
    {
        for (var i:int = 0; i < numChildren; i++) {
            var child:GameSprite = getChildAt(i) as GameSprite;
            if (child) {
                child.setActive(active);
            }
        }
        this.active = active;
    }
    
    // Yeah, this class imitates Unity's GameObject a bit.
    public function start():void {}
    public function onDestroy():void {}
    public function update():void {}
    
}

class TitlePanel extends GameSprite
{
    public override function start():void
    {
        var titleText:TextField = Helper.createTextField("LANDOLT WARS");
        addChild(titleText);
        
        BetweenAS3.tween(titleText,
            { x: stage.stageWidth / 2 - titleText.width / 2, y: stage.stageHeight * 0.125 },
            { x: stage.stageWidth / 2 - titleText.width / 2, y: stage.stageHeight * -0.2 },
            0.7,
            Quint.easeOut).play();
        
        var c:LandoltCShape = new LandoltCShape();
        c.x = stage.stageWidth / 2;
        c.y = stage.stageHeight * 0.5;
        addChild(c);
        
        BetweenAS3.tween(c,
            { scaleX: 1, scaleY: 1, alpha: 1 },
            { scaleX: 1.5, scaleY: 1.5, alpha: 0 },
            0.7,
            Quint.easeOut).play();
        
        var getin:TextField = Helper.createTextField("<=== GET IN!!!");
        getin.x = stage.stageWidth * 0.61;
        getin.y = c.y - 12;
        addChild(getin);
        
        BetweenAS3.from(getin,
            { alpha: 0 },
            1, 
            Quint.easeOut).play();
        
        var startButton:Button = new Button("START", onStart);
        addChild(startButton);
        
        BetweenAS3.tween(startButton,
            { x: stage.stageWidth / 2, y: stage.stageHeight * 0.8 },
            { x: stage.stageWidth / 2, y: stage.stageHeight * 1.2 },
            0.7,
            Quint.easeOut).play();
    }
    
    private function onStart():void
    {
        Main(root).startGame();
        
        BetweenAS3.serial(
            BetweenAS3.to(this, { alpha: 0 }, 0.3),
            BetweenAS3.removeFromParent(this)
        ).play();
    }
}

class GameField extends GameSprite
{
    private var difficulty:Number;
    
    private var newLandoltCTime:Number = 0.7;
    
    public override function start():void
    {
        name = "GameField";
        
        addChild(new Pointer());
    }
    
    public override function update():void
    {
        difficulty = MyMath.clamp(MyMath.map(getFrame() / 60, 0, 60, 0, 1), 0, 1);
        
        var landoltCNum:int = 0;
        for (var i:int = 0; i < numChildren; i++) {
            var landoltC:LandoltC = getChildAt(i) as LandoltC;
            if (landoltC) {
                landoltCNum++;
            }
        }
        
        if (getFrame() > 60 && landoltCNum == 0) {
            newLandoltCTime = 0;
        }
        
        newLandoltCTime -= 0.016667;
        if (newLandoltCTime < 0 && landoltCNum < 5) {
            addChildAt(new LandoltC(), 0);
            
            newLandoltCTime = MyMath.map(difficulty, 0, 1, 3, 1);
        }
    }
}

class Pointer extends GameSprite 
{
    public override function update():void
    {
        var g:Graphics = graphics;
        
        g.clear();
        g.lineStyle(10, 0x000000, 0.1);
        g.moveTo(mouseX, mouseY);
        g.lineTo(mouseX + 500, mouseY / 3 + 600);
        g.lineStyle(10, 0x666666, 1);
        g.moveTo(mouseX, mouseY);
        g.lineTo(mouseX / 1.5 + 600, mouseY / 3 + 400);
    }
}

class LandoltCShape extends Shape
{
    static public const OUTER_RADIUS:Number = 100;
    static public const INNER_RADIUS:Number = OUTER_RADIUS * (1.5 / 2.5);
    
    public function LandoltCShape()
    {
        var g:Graphics = graphics;
        
        g.beginFill(0x000000);
        drawArc(g, OUTER_RADIUS, MyMath.toRadian(15), MyMath.toRadian(360 - 15), true);
        drawArc(g, INNER_RADIUS, MyMath.toRadian(360 - 26), MyMath.toRadian(26), false);
        g.endFill();
    }
    
    private function drawArc(g:Graphics, radius:Number, start:Number, end:Number, moveFirst:Boolean):void
    {
        const SEGMENT:int = 8;
        
        var angle:Number = start;
        var deltaAngle:Number = (end - start) / SEGMENT;
        
        for (var i:int = 0; i <= SEGMENT; i++) {
            var x:Number = Math.cos(angle) * radius;
            var y:Number = Math.sin(angle) * radius;
            if (moveFirst && i == 0) {
                g.moveTo(x, y);
            } else if (i == 0) {
                g.lineTo(x, y);
            } else {
                var cAngle:Number = angle - deltaAngle / 2;
                var cRadius:Number = radius / Math.cos(deltaAngle / 2);
                
                var cx:Number = Math.cos(cAngle) * cRadius;
                var cy:Number = Math.sin(cAngle) * cRadius;
                g.curveTo(cx, cy, x, y);
            }
            angle += deltaAngle;
        }
    }
    
}

class LandoltC extends GameSprite
{
    private var vx:Number;
    private var vy:Number;
    private var va:Number;
    
    private var alive:Boolean = true;
    
    public override function start():void
    {
        addChild(new LandoltCShape());
        
        var dx:Number = MyMath.random(LandoltCShape.OUTER_RADIUS, 465 - LandoltCShape.OUTER_RADIUS);
        var dy:Number = MyMath.random(LandoltCShape.OUTER_RADIUS, 465 - LandoltCShape.OUTER_RADIUS);
        var a:Number = MyMath.random(0, Math.PI * 2);
        
        var len:Number = 465 * 1.41421356 + LandoltCShape.OUTER_RADIUS;
        x = dx - Math.cos(a) * len;
        y = dy - Math.sin(a) * len;
        
        var speed:Number = 2;
        vx = Math.cos(a) * speed;
        vy = Math.sin(a) * speed;
        
        while (!MyMath.inRange(x, -LandoltCShape.OUTER_RADIUS, 465 + LandoltCShape.OUTER_RADIUS) || 
               !MyMath.inRange(y, -LandoltCShape.OUTER_RADIUS, 465 + LandoltCShape.OUTER_RADIUS)) {
            x += vx;
            y += vy;
        }
        
        rotation = MyMath.random(-180, 180);
        
        va = MyMath.random(0.1, 1);
        if (MyMath.random(0, 1) < 0.5) {
            va = -va;
        }
    }
    
    public override function update():void
    {
        const MARGIN:Number = LandoltCShape.OUTER_RADIUS * 0.5;
        
        if ((x + vx < MARGIN && vx < 0) || (x + vx > 465 - MARGIN && vx > 0)) {
            vx = -vx;
        }
        if ((y + vy < MARGIN && vy < 0) || (y + vy > 465 - MARGIN && vy > 0)) {
            vy = -vy;
        }
        
        x += vx;
        y += vy;
        rotation += va;
        
        if (!alive) {
            alpha -= 0.1;
            scaleX += 0.2;
            scaleY += 0.2;
            
            if (alpha < 0) {
                destroy();
            }
            return;
        }
        
        if (isInner(stage.mouseX, stage.mouseY)) {
            Object(root).score.increment();
            alive = false;
        }
        
        if (hitTestPoint(stage.mouseX, stage.mouseY, true)) {
            if (!Object(root).getChildByName("GameOver")) {
                Object(root).addChild(new GameOver());
            }
            return;
        }
    }
    
    private function isInner(mouseX:Number, mouseY:Number):Boolean
    {
        var dx:Number = mouseX - x;
        var dy:Number = mouseY - y;
        
        return (dx * dx + dy * dy < MyMath.square(LandoltCShape.INNER_RADIUS));
    }
}

class Board extends GameSprite
{
    private var level:int = 0;
    
    public override function start():void
    {
        var g:Graphics = graphics;
        
        var matrix:Matrix = new Matrix();
        matrix.createGradientBox(stage.stageWidth, stage.stageHeight, 0, -100, -100);
        
        g.beginGradientFill(GradientType.RADIAL, [0xbbb6b3, 0x9a9da2], null, [0, 255], matrix);
        g.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
        g.endFill();
        
        g.beginFill(0xe8e8e8);
        g.moveTo(400, 0); g.lineTo(300, 100); g.lineTo(420, 0);
        g.moveTo(450, 0); g.lineTo(320, 100); g.lineTo(470, 0);
        g.endFill();
    }
    
    public override function update():void
    {
        if (level > 0) {
            level++;
            if (level <= 11) {
                setLight(level % 2 == 1);
            }
        }
    }
    
    public function turnOn():void
    {
        level = 1;
    }
    
    public function turnOff():void
    {
        level = 0;
        setLight(false);
    }
    
    private function setLight(flag:Boolean):void
    {
        var offset:int = flag ? 80 : 0;
        transform.colorTransform = new ColorTransform(1, 1, 1, 1, offset, offset, offset);
    }
    
}

class Score extends TextField 
{
    private var integer:int;
    private var decimal:int;
    
    public function Score()
    {
        defaultTextFormat = new TextFormat("Arial", 30, 0x000000);
        autoSize = TextFieldAutoSize.LEFT;
        selectable = false;
        
        reset();
    }
    
    public function reset():void
    {
        integer = 0;
        decimal = 0;
        render();
    }
    
    public function increment():void
    {
        if (++decimal >= 10) {
            decimal = 0;
            integer++;
        }
        render();
    }
    
    private function render():void
    {
        text = integer + "." + decimal;
    }
}

class GameOver extends GameSprite 
{
    private var gameOverText:TextField;
    
    public override function start():void 
    {
        name = "GameOver";
        
        gameOverText = Helper.createTextField("GAME OVER");
        gameOverText.x = 465 / 2 - gameOverText.width / 2;
        gameOverText.y = 465 / 2 - gameOverText.height / 2;
        addChild(gameOverText);
        
        var gameField:GameField = GameField(Object(root).getChildByName("GameField"));
        gameField.setActive(false);
        gameField.transform.colorTransform = new ColorTransform(1, 1, 1, 1, 128, 128, 128);
        
        stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
    }
    
    public override function onDestroy():void
    {
        stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
        Object(root).startTitle();
    }
    
    private function mouseDownHandler(e:MouseEvent):void 
    {
        destroy();
    }
    
    public override function update():void
    {
        gameOverText.visible = (getFrame() % 20 < 12);
        
        if (getFrame() > 150) {
            destroy();
        }
    }
}

class Button extends SimpleButton
{
    private var onClick:Function;
    
    function Button(name:String, onClick:Function)
    {
        this.onClick = onClick;
        
        var button:Sprite = new Sprite();
        var g:Graphics = button.graphics;
        g.lineStyle(1.5, 0x000000);
        g.beginFill(0x000000, 0);
        g.drawRoundRect(-100, 0, 200, 30, 30, 30);
        g.endFill();
        
        var caption:TextField = Helper.createTextField(name);
        caption.x = -caption.width / 2;
        button.addChild(caption);
        
        upState = button;
        overState = button;
        downState = button;
        hitTestState = button;
        
        addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
    }
    
    private function mouseDownHandler(e:MouseEvent):void 
    {
        onClick();
    }
}

class Helper
{
    static public function createTextField(text:String):TextField
    {
        var textField:TextField = new TextField();
        textField.autoSize = TextFieldAutoSize.LEFT;
        textField.defaultTextFormat = new TextFormat("Arial", 20, 0x333333);
        textField.text = text;
        textField.selectable = false;
        
        return textField;
    }
    
    static public function traceDisplayList(displayObject:DisplayObject, indent:String = ""):void
    {
        trace(indent + displayObject, displayObject.name);
        
        var container:DisplayObjectContainer = displayObject as DisplayObjectContainer;
        if (container) {
            for (var i:int = 0; i < container.numChildren; i++) {
                var child:DisplayObject = container.getChildAt(i);
                traceDisplayList(child, indent + " ");
            }
        }
    }
}

class MyMath
{
    
    public static function clamp(value:Number, min:Number, max:Number):Number
    {
        // correct min and max order
        if (min > max) {
            var temp:Number = min;
            min = max;
            max = temp;
        }
        
        if (value < min) {
            return min;
        }
        if (value > max) {
            return max;
        }
        return value;
    }
    
    public static function random(min:Number, max:Number):Number
    {
        return min + (max - min) * Math.random();
        // return lerp(min, max, Math.random());
    }
    
    public static function randomInt(min:int, max:int):int
    {
        // 0.683 secs
        //return Math.floor(random(min, max + 1));
        
        // 0.425 secs
        return min + int((max - min + 1) * Math.random());
    }
    
    public static function map(value:Number, s0:Number, s1:Number, d0:Number, d1:Number):Number
    {
        // Avoid zero division.
        if (s0 == s1) {
            // Is this appropriate?
            return d0;
        }
        
        return d0 + (d1 - d0) * ((value - s0) / (s1 - s0));
    }
    
    public static function lerp(a:Number, b:Number, t:Number):Number
    {
        return a + (b - a) * t;
    }
    
    public static function inRange(value:Number, min:Number, max:Number):Boolean
    {
        return (min <= value && value <= max);
    }
    
    public static const PI2:Number = Math.PI * 2;
    private static const TO_DEGREE:Number = 360 / PI2;
    private static const TO_RADIAN:Number = PI2 / 360;
    
    public static function toRadian(degree:Number):Number
    {
        return degree * TO_RADIAN;
    }
    
    public static function toDegree(radian:Number):Number
    {
        return radian * TO_DEGREE;
    }
    
    public static function square(value:Number):Number
    {
        return value * value;
    }
}