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

Billiards (3)

////////////////////////////////////////////////////////////////////////////////
// Billiards (3)
//
// ビリヤードもどき (4) [AS2.0]
// http://www.project-nya.jp/modules/weblog/details.php?blog_id=839
//
// TODO
// 1. 不具合(すり抜け)対策 2. 不具合(すり代わり)対策
////////////////////////////////////////////////////////////////////////////////
Get Adobe Flash player
by ProjectNya 13 Jul 2011
    Embed
/**
 * Copyright ProjectNya ( http://wonderfl.net/user/ProjectNya )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/yITJ
 */

////////////////////////////////////////////////////////////////////////////////
// Billiards (3)
//
// ビリヤードもどき (4) [AS2.0]
// http://www.project-nya.jp/modules/weblog/details.php?blog_id=839
//
// TODO
// 1. 不具合(すり抜け)対策 2. 不具合(すり代わり)対策
////////////////////////////////////////////////////////////////////////////////

package {

    import flash.display.Sprite;
    import flash.display.StageScaleMode;
     import flash.display.StageAlign;
    import flash.display.StageDisplayState;
    import flash.display.Shape;
    import flash.geom.Rectangle;
    import flash.events.Event;
    import flash.events.MouseEvent;

    [SWF(backgroundColor="#EEEEEE", width="465", height="465", frameRate="30")]

    public class Main extends Sprite {
        private var base:Shape;
        private var controller:Sprite;
        private var fullscreenBtn:Btn;
        private var normalBtn:Btn;
        private var rect:Rectangle;
        private var area:Rectangle;
        private var billiards:Billiards;

        public function Main() {
            //Wonderfl.disable_capture();
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.addEventListener(Event.RESIZE, resize, false, 0, true);
            init();
        }

        private function init():void {
            base = new Shape();
            base.graphics.beginFill(0x339900);
            base.graphics.drawRect(0, 0, 465, 465);
            base.graphics.endFill();
            base.graphics.beginFill(0x336600);
            base.graphics.drawRect(5, 5, 455, 455);
            base.graphics.endFill();
            controller = new Sprite();
            addChild(controller);
            controller.x = 232;
            controller.y = 445;
            fullscreenBtn = new Btn();
            controller.addChild(fullscreenBtn);
            fullscreenBtn.init({label: "play", width: 80});
            fullscreenBtn.addEventListener(MouseEvent.CLICK, click, false, 0, true);
            normalBtn = new Btn();
            controller.addChild(normalBtn);
            normalBtn.init({label: "close", width: 80});
            normalBtn.addEventListener(MouseEvent.CLICK, click, false, 0, true);
            normalBtn.visible = false;
            rect = new Rectangle(0, 0, 1200, 600);
            billiards = new Billiards(rect);
            resize();
        }
        private function resize(evt:Event = null):void {
            update();
            screenMode();
        }
        private function update():void {
            var sw:uint = stage.stageWidth;
            var sh:uint = stage.stageHeight;
            var cx:uint = uint(sw/2);
            var cy:uint = uint(sh/2);
            billiards.x = cx - 600;
            billiards.y = cy - 300;
            controller.x = cx;
            if (sh == 465) {
                controller.y = cy;
            } else {
                controller.y = cy + 340;
            }
        }
        private function screenMode():void {
            if (stage.displayState == StageDisplayState.NORMAL) {
                fullscreenBtn.visible = true;
                normalBtn.visible = false;
                addChildAt(base, 0);
                if (contains(billiards)) {
                    billiards.stop();
                    removeChild(billiards);
                }
            } else {
                fullscreenBtn.visible = false;
                normalBtn.visible = true;
                if (contains(base)) removeChild(base);
                addChildAt(billiards, 0);
                billiards.start();
            }
        }
        private function click(evt:MouseEvent):void {
            if (stage.displayState == StageDisplayState.NORMAL) {
                stage.displayState = StageDisplayState.FULL_SCREEN;
            } else {
                stage.displayState = StageDisplayState.NORMAL;
            }
        }

    }

}


//////////////////////////////////////////////////
// Billiardsクラス
//////////////////////////////////////////////////

import flash.display.Sprite;
import flash.display.Shape;
import flash.geom.Rectangle;
import flash.events.Event;
import flash.geom.Matrix;
import flash.display.GradientType;
import flash.display.SpreadMethod;
import flash.display.InterpolationMethod;
import flash.utils.Timer;
import flash.events.TimerEvent;

class Billiards extends Sprite {
    private var rect:Rectangle;
    private static var max:uint = 9;
    private static var radius:uint = 25;
    private var area:Rectangle;
    private static var colors:Array;
    private var base:Sprite;
    private var overlay:Shape;
    public var line:Shape;
    private var balls:Array;
    private var stocks:Array;
    private var pockets:Array;
    private static var limit:uint = radius*2;
    private var xMin:uint;
    private var xMax:uint;
    private var yMin:uint;
    private var yMax:uint;
    public var manager:SoundManager;
    private var source1:String = "http://www.project-nya.jp/images/flash/billiards/shoot.mp3";
    private var source2:String = "http://www.project-nya.jp/images/flash/billiards/hit.mp3";
    private var source3:String = "http://www.project-nya.jp/images/flash/billiards/drop.mp3";

    public function Billiards(r:Rectangle) {
        rect = r;
        init();
    }

    private function init():void {
        pockets = new Array();
        draw();
        colors = new Array();
        colors.push(0xFFFFFF);
        colors.push(0xFF9900);
        colors.push(0x0066FF);
        colors.push(0xFF0066);
        colors.push(0x6633CC);
        colors.push(0x339900);
        colors.push(0xFF6600);
        colors.push(0x0033FF);
        colors.push(0xFF3366);
        colors.push(0x993399);
        colors.push(0x006600);
        area = new Rectangle(rect.x+radius+5, rect.y+radius+5, rect.width-radius*2-10, rect.height-radius*2-10);
        xMin = area.left;
        xMax = area.right;
        yMin = area.top;
        yMax = area.bottom;
        manager = new SoundManager();
        manager.load(source1, "shoot", 0.4);
        manager.load(source2, "hit", 0.2);
        manager.load(source3, "drop", 1);
        setup();
    }
    private function setup():void {
        balls = new Array();
        for (var n:uint = 0; n <= max; n++) {
            var ball:Ball = new Ball(this, radius, colors[n]);
            addChild(ball);
            ball.x = area.x + Math.random()*area.width;
            ball.y = area.y + Math.random()*area.height;
            ball.setup(n);
            ball.addEventListener(Event.COMPLETE, remove, false, 0, true);
            balls.push(ball);
        }
    }
    public function start():void {
        addEventListener(Event.ENTER_FRAME, update, false, 0, true);
    }
    public function stop():void {
        removeEventListener(Event.ENTER_FRAME, update);
    }
    private function update(evt:Event):void {
        position();
        checkHit();
        motion();
        checkPocket();
        manageDepths();
    }
    private function position():void {
        for (var n:uint = 0; n < balls.length; n++) {
            var ball:Ball = balls[n];
            ball.position();
        }
    }
    private function checkHit():void {
        for (var n:uint = 0; n < balls.length; n++) {
            var ball0:Ball = balls[n];
            for (var t:uint = n+1; t < balls.length; t++) {
                var ball1:Ball = balls[t];
                repulsion(ball0, ball1);
            }
        }
    }
    private function motion():void {
        against();
        for (var n:uint = 0; n < balls.length; n++) {
            var ball:Ball = balls[n];
            if (!ball.dropping) {
                ball.motion();
            } else {
                ball.drop();
            }
        }
    }
    private function checkPocket():void {
        for (var n:uint = 0; n < balls.length; n++) {
            var ball:Ball = balls[n];
            for (var p:uint = 0; p < 6; p++) {
                var pocket:Sprite = pockets[p];
                if (ball.hitTestObject(pocket)) {
                    ball.dropIn(pocket.x, pocket.y);
                }
            }
        }
    }
    private function repulsion(ball0:Ball, ball1:Ball):void {
        var x0:Number = ball0.px;
        var y0:Number = ball0.py;
        var vx0:Number = ball0.vx;
        var vy0:Number = ball0.vy;
        var x1:Number = ball1.px;
        var y1:Number = ball1.py;
        var vx1:Number = ball1.vx;
        var vy1:Number = ball1.vy;
        var d:Number = distance(x0, x1, y0, y1);
        if (d <= limit) {
            var l:Number = rebound(d, limit);
            var v0:Number = speed(vx0, vy0);
            var v1:Number = speed(vx1, vy1);
            var r:Number = (v0 + v1)/d*2 + l;
            ball0.repulsion((x0 - x1)*r, (y0 - y1)*r);
            ball1.repulsion((x1 - x0)*r, (y1 - y0)*r);
        }
    }
    private function distance(x0:Number, x1:Number, y0:Number, y1:Number):Number {
        var d:Number = Math.sqrt((x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0));
        return d;
    }
    private function rebound(d:Number, l:Number):Number {
        var r:Number = (l - d)/l;
        return r;
    }
    private function speed(vx:Number, vy:Number):Number {
        var r:Number = Math.sqrt(vx*vx + vy*vy);
        return r;
    }
    private function against():void {
        for (var n:uint = 0; n < balls.length; n++) {
            var ball:Ball = balls[n];
            var wall:Number;
            if (ball.px < (wall = xMin) || ball.px > (wall = xMax)) {
                ball.against("x", wall);
            } else if (ball.py < (wall = yMin) || ball.py > (wall = yMax)) {
                ball.against("y", wall);
            }
        }
    }
    private function manageDepths():void {
        balls.sortOn(["y", "id"], [Array.CASEINSENSITIVE | Array.NUMERIC, Array.DESCENDING | Array.NUMERIC]);
        for (var n:uint = 0; n < balls.length; n++) {
            var ball:Ball = balls[n];
            addChildAt(ball, n+2);
        }
    }
    private function remove(evt:Event):void {
        var ball:Ball = Ball(evt.target);
        ball.removeEventListener(Event.COMPLETE, remove);
        for (var n:uint = 0; n < balls.length; n++) {
            if (balls[n] == ball) {
                balls.splice(n, 1);
            }
        }
        removeChild(ball);
        ball = null;
        if (balls.length == 1) {
            var cue:Ball = balls[0];
            cue.removeCueLine();
            var timer:Timer = new Timer(2000, 1);
            timer.addEventListener(TimerEvent.TIMER_COMPLETE, finish, false, 0, true);
            timer.start();
        }
    }
    private function finish(evt:TimerEvent):void {
        var cue:Ball = balls[0];
        removeChild(cue);
        cue = null;
        setup();
    }
    private function draw():void {
        base = new Sprite();
        base.graphics.beginFill(0x339900);
        base.graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
        base.graphics.endFill();
        base.graphics.beginFill(0x336600);
        base.graphics.drawRect(rect.x+5, rect.y+5, rect.width-10, rect.height-10);
        base.graphics.endFill();
        drawHoles();
        drawPockets();
        overlay = new Shape();
        overlay.graphics.beginFill(0x000000);
        overlay.graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
        overlay.graphics.endFill();
        addChild(base);
        addChild(overlay);
        mask = overlay;
    }
    private function drawHoles():void {
        createHole(rect.x+10, rect.y+10);
        createHole(rect.right-10, rect.y+10);
        createHole(rect.x+10, rect.bottom-10);
        createHole(rect.right-10, rect.bottom-10);
        createHole(rect.width/2, rect.y+10);
        createHole(rect.width/2, rect.bottom-10);
    }
    private function createHole(hx:uint, hy:uint):void {
        var hole:Shape = new Shape();
        hole.x = hx;
        hole.y = hy;
        var colors:Array = [0x000000, 0x003300];
        var alphas:Array = [1, 1];
        var ratios:Array = [51, 204];
        var matrix:Matrix = new Matrix();
        matrix.createGradientBox(80, 80, 0, -40, -40);
        hole.graphics.beginGradientFill(GradientType.RADIAL, colors, alphas, ratios, matrix, SpreadMethod.PAD, InterpolationMethod.RGB, 0);
        hole.graphics.drawCircle(0, 0, 40);
        hole.graphics.endFill();
        base.addChild(hole);
    }
    private function drawPockets():void {
        createPocket(rect.x+10, rect.y+10);
        createPocket(rect.right-10, rect.y+10);
        createPocket(rect.x+10, rect.bottom-10);
        createPocket(rect.right-10, rect.bottom-10);
        createPocket(rect.width/2, rect.y+10);
        createPocket(rect.width/2, rect.bottom-10);
    }
    private function createPocket(px:uint, py:uint):void {
        var pocket:Sprite = new Sprite();
        pocket.x = px;
        pocket.y = py;
        pocket.graphics.beginFill(0xFFFFFF, 0);
        pocket.graphics.drawCircle(0, 0, 10);
        pocket.graphics.endFill();
        base.addChild(pocket);
        pockets.push(pocket);
    }

}


//////////////////////////////////////////////////
// Ballクラス
//////////////////////////////////////////////////

import flash.display.Sprite;
import flash.display.Shape;
import flash.filters.DropShadowFilter;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.display.GradientType;
import flash.display.SpreadMethod;
import flash.display.InterpolationMethod;
import flash.display.BlendMode;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.AntiAliasType;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;

class Ball extends Sprite {
    private var billiards:Billiards;
    public var id:uint;
    private var radius:uint;
    private var color:uint;
    private var ball:Sprite;
    private var base:Shape;
    private var shadow:Shape;
    private var light:Shape;
    private var reflection:Shape;
    private var txt:TextField;
    private var shade:Shape;
    private static var bColor:uint = 0xFFFFFF;
    private static var sColor:uint = 0x000000;
    public var px:Number;
    public var py:Number;
    private var xTarget:Number;
    private var yTarget:Number;
    public var vx:Number;
    public var vy:Number;
    private static var deceleration:Number = 0.25;
    private static var rebounce:Number = 1.6;
    private static var cueRange:Number = 1.6;
    public var dropping:Boolean = false;
    private var dropped:Boolean = false;

    public function Ball(b:Billiards, r:uint, c:uint) {
        billiards = b;
        radius = r;
        color = c;
        draw();
    }

    private function draw():void {
        shade = new Shape();
        addChild(shade);
        shade.y = radius;
        createShade();
        ball = new Sprite();
        addChild(ball);
        base = new Shape();
        ball.addChild(base);
        shadow = new Shape();
        ball.addChild(shadow);
        light = new Shape();
        ball.addChild(light);
        reflection = new Shape();
        ball.addChild(reflection);
        createBase();
        createShadow();
        createLight();
        createReflect();
    }
    public function setup(n:uint):void {
        id = n;
        if (id > 0) {
            txt = new TextField();
            ball.addChild(txt);
            createTxt();
        } else {
            setCueBall();
            setCueLine();
        }
        xTarget = px = x;
        yTarget = py = y;
    }
    private function setCueBall():void {
        billiards.addEventListener(MouseEvent.MOUSE_DOWN, press, false, 0, true);
        billiards.addEventListener(MouseEvent.MOUSE_MOVE, track, false, 0, true);
        billiards.addEventListener(MouseEvent.MOUSE_UP, release, false, 0, true);
    }
    private function clearCueLine():void {
        billiards.removeEventListener(MouseEvent.MOUSE_DOWN, press);
        billiards.removeEventListener(MouseEvent.MOUSE_MOVE, track);
        billiards.line.graphics.clear();
    }
    private function press(evt:MouseEvent):void {
        billiards.manager.play("shoot");
        xTarget = px + mouseX*cueRange;
        yTarget = py + mouseY*cueRange;
    }
    private function release(evt:MouseEvent):void {
        billiards.line.graphics.clear();
    }
    private function setCueLine():void {
        billiards.line = new Shape();
        billiards.addChildAt(billiards.line, 1);
    }
    private function track(evt:MouseEvent):void {
        if (billiards.line) {
            billiards.line.graphics.clear();
            billiards.line.graphics.lineStyle(40, bColor, 0.2);
            billiards.line.graphics.moveTo(px, py);
            billiards.line.graphics.lineTo(px + mouseX, py + mouseY);
            billiards.line.graphics.lineStyle(40, bColor, 0.1);
            billiards.line.graphics.lineTo(px + mouseX*cueRange, py + mouseY*cueRange);
        }
        evt.updateAfterEvent();
    }
    public function repulsion(dx:Number, dy:Number):void {
        billiards.manager.play("hit");
        if (id != 0) {
            dx *= rebounce;
            dy *= rebounce;
        }
        xTarget = px + dx;
        yTarget = py + dy;
    }
    public function against(direction:String, wall:Number):void {
        var target:Number = this[direction+"Target"];
        this[direction+"Target"] = wall*2 - target;
    }
    public function position():void {
        vx = (xTarget - px)*deceleration;
        vy = (yTarget - py)*deceleration;
        px += vx;
        py += vy;
    }
    public function motion():void {
        x = px;
        y = py;
    }
    public function dropIn(dx:Number, dy:Number):void {
        if (!dropping) {
            dropping = true;
            billiards.manager.play("drop");
        }
        if (id == 0) clearCueLine();
        x = px = xTarget = dx;
        y = py = yTarget = dy;
    }
    public function drop():void {
        alpha -= 0.05;
        if (alpha <= 0) {
            if (id == 0) {
                visible = false;
                y = py = yTarget = -100;
                if (!dropped) {
                    dropped = true;
                    var timer:Timer = new Timer(1000, 1);
                    timer.addEventListener(TimerEvent.TIMER_COMPLETE, resetCueBall, false, 0, true);
                    timer.start();
                }
            } else {
                dropping = false;
                dispatchEvent(new Event(Event.COMPLETE));
            }
        }
    }
    private function resetCueBall(evt:TimerEvent):void {
        evt.target.removeEventListener(TimerEvent.TIMER_COMPLETE, resetCueBall);
        dropping = false;
        dropped = false;
        x = px = xTarget = 300;
        y = py = yTarget = 200;
        alpha = 1;
        visible = true;
        setCueBall();
        setCueLine();
    }
    public function removeCueLine():void {
        billiards.removeChild(billiards.line);
        billiards.line = null;
    }
    private function createBase():void {
        base.graphics.clear();
        base.graphics.beginFill(color, 0.8);
        base.graphics.drawCircle(0, 0, radius);
        base.graphics.endFill();
    }
    private function createShadow():void {
        var colors:Array = [sColor, sColor, sColor];
        var alphas:Array = [0, 0.2, 0.3];
        var ratios:Array = [0, 191, 255];
        var matrix:Matrix = new Matrix();
        matrix.createGradientBox(radius*3.2, radius*3.2, 0, -radius*2, -radius*2);
        shadow.graphics.beginGradientFill(GradientType.RADIAL, colors, alphas, ratios, matrix, SpreadMethod.PAD, InterpolationMethod.RGB, 0);
        shadow.graphics.drawCircle(0, 0, radius);
        shadow.graphics.endFill();
        shadow.blendMode = BlendMode.HARDLIGHT;
    }
    private function createLight():void {
        var colors:Array = [bColor, bColor, bColor];
        var alphas:Array = [1, 0.2, 0];
        var ratios:Array = [0, 191, 255];
        var matrix:Matrix = new Matrix();
        matrix.createGradientBox(radius*3.2, radius*3.2, 0, -radius*2, -radius*2);
        light.graphics.beginGradientFill(GradientType.RADIAL, colors, alphas, ratios, matrix, SpreadMethod.PAD, InterpolationMethod.RGB, 0);
        light.graphics.drawCircle(0, 0, radius);
        light.graphics.endFill();
        light.blendMode = BlendMode.OVERLAY;
    }
    private function createReflect():void {
        var colors:Array = [bColor, bColor];
        var alphas:Array = [0.7, 0];
        var ratios:Array = [0, 191];
        var matrix:Matrix = new Matrix();
        var w:Number = radius*1.44;
        var h:Number = radius*1.35;
        var yOffset:Number = radius*0.95;
        matrix.createGradientBox(w, h, 0.5*Math.PI, -w*0.5, -yOffset);
        reflection.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix, SpreadMethod.PAD, InterpolationMethod.RGB, 0);
        reflection.graphics.drawEllipse(-w*0.5, -yOffset, w, h);
        reflection.graphics.endFill();
    }
    private function createTxt():void {
        txt.x = -radius*0.5;
        txt.y = -radius*0.6;
        txt.width = radius;
        txt.height = radius;
        txt.type = TextFieldType.DYNAMIC;
        txt.selectable = false;
        //txt.embedFonts = true;
        //txt.antiAliasType = AntiAliasType.ADVANCED;
        var tf:TextFormat = new TextFormat();
        tf.font = "_ゴシック";
        tf.size = 20;
        tf.align = TextFormatAlign.CENTER;
        txt.defaultTextFormat = tf;
        txt.text = String(id);
        txt.textColor = bColor;
        var glow:GlowFilter = new GlowFilter(bColor, 1, 4, 4, 6, 3, false, true);
        txt.filters = [glow];
    }
    private function createShade():void {
        shade.graphics.beginFill(sColor, 0.6);
        shade.graphics.drawEllipse(-radius*0.75, -radius*0.1775, radius*1.5, radius*0.375);
        shade.graphics.endFill();
        var shadow:DropShadowFilter = new DropShadowFilter(0, 90, sColor, 0.5, radius*0.15, radius*0.15, 1, 3, false, false, true);
        shade.filters = [shadow];
    }

}


//////////////////////////////////////////////////
// SoundManagerクラス
//////////////////////////////////////////////////

class SoundManager {
    private var sounds:Object;
    private var levels:Object;

    public function SoundManager() {
        init();
    }

    private function init():void {
        sounds = new Object();
        levels = new Object();
    }
    public function load(file:String, id:String, level:Number):void {
        var se:SoundEffect = new SoundEffect();
        se.load(file, id);
        sounds[id] = se;
        levels[id] = level;
    }
    public function play(id:String):void {
        var se:SoundEffect = sounds[id];
        var volume:Number = levels[id];
        se.play(id, volume);
    }

}


//////////////////////////////////////////////////
// SoundEffectクラス
//////////////////////////////////////////////////

import flash.events.EventDispatcher;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.events.ProgressEvent;
import flash.net.URLRequest;

class SoundEffect extends EventDispatcher {
    private static var soundList:Object;
    private var sound:Sound;
    private var channel:SoundChannel;
    private static var initialized:Boolean = false;
    private var volume:Number;
    private var looping:Boolean = false;

    public function SoundEffect() {
        if (!initialized) initialize();
    }

    private static function initialize():void {
        initialized = true;
        soundList = new Object();
    }
    public function init(Snd:Class, id:String):void {
        var snd:Sound = new Snd();
        soundList[id] = snd;
    }
    public function load(file:String, id:String):void {
        var snd:Sound = new Sound();
        snd.load(new URLRequest(file));
        snd.addEventListener(ProgressEvent.PROGRESS, progress, false, 0, true);
        snd.addEventListener(Event.COMPLETE, loaded, false, 0, true);
        soundList[id] = snd;
    }
    public function play(id:String, vol:Number, loop:Boolean = false):void {
        if (channel != null) channel.stop();
        sound = soundList[id];
        volume = vol;
        looping = loop;
        channel = sound.play();
        var transform:SoundTransform = channel.soundTransform;
        transform.volume = volume;
        channel.soundTransform = transform;
        if (looping) {
            channel.addEventListener(Event.SOUND_COMPLETE, complete, false, 0, true);
        }
    }
    public function stop():void {
        if (channel != null) {
            channel.stop();
            channel.removeEventListener(Event.SOUND_COMPLETE, complete);
        }
    }
    private function progress(evt:ProgressEvent):void {
        dispatchEvent(evt);
    }
    private function loaded(evt:Event):void {
        dispatchEvent(evt);
    }
    private function complete(evt:Event):void {
        channel.removeEventListener(Event.SOUND_COMPLETE, complete);
        if (looping) {
            channel = sound.play(0);
            channel.addEventListener(Event.SOUND_COMPLETE, complete, false, 0, true);
            var transform:SoundTransform = channel.soundTransform;
            transform.volume = volume;
            channel.soundTransform = transform;
        }
    }

}


//////////////////////////////////////////////////
// Btnクラス
//////////////////////////////////////////////////

import flash.display.Sprite;
import flash.display.Shape;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.AntiAliasType;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.filters.GlowFilter;
import flash.events.MouseEvent;

class Btn extends Sprite {
    public var id:uint;
    private var shade:Shape;
    private var bottom:Shape;
    private var light:Shape;
    private var base:Shape;
    private var txt:TextField;
    private var label:String = "";
    private static var fontType:String = "_ゴシック";
    private var _width:uint = 60;
    private static var _height:uint = 20;
    private static var corner:uint = 5;
    private var type:uint = 1;
    private static var bColor:uint = 0xFFFFFF;
    private static var sColor:uint = 0x000000;
    private static var upColor:uint = 0x666666;
    private static var overColor:uint = 0x333333;
    private static var offColor:uint = 0x999999;
    private static var gColor:uint = 0x0099FF;
    private var blueGlow:GlowFilter;
    private var shadeGlow:GlowFilter;
    private var _clicked:Boolean = false;
    private var _enabled:Boolean = true;

    public function Btn() {
    }

    public function init(option:Object):void {
        if (option.id != undefined) id = option.id;
        if (option.label != undefined) label = option.label;
        if (option.width != undefined) _width = option.width;
        if (option.type != undefined) type = option.type;
        draw();
    }
    private function draw():void {
        switch (type) {
            case 1 :
                bColor = 0xFFFFFF;
                sColor = 0x000000;
                upColor = 0x666666;
                overColor = 0x333333;
                offColor = 0x999999;
                break;
            case 2 :
                bColor = 0x000000;
                sColor = 0xFFFFFF;
                upColor = 0x666666;
                overColor = 0x999999;
                offColor = 0x333333;
                break;
        }
        blueGlow = new GlowFilter(gColor, 0.6, 5, 5, 2, 3, false, true);
        shadeGlow = new GlowFilter(sColor, 0.3, 4, 4, 2, 3, false, true);
        shade = new Shape();
        bottom = new Shape();
        light = new Shape();
        base = new Shape();
        txt = new TextField();
        addChild(shade);
        addChild(bottom);
        addChild(light);
        addChild(base);
        addChild(txt);
        createBase(shade, _width, _height, corner, sColor);
        shade.filters = [shadeGlow];
        createBase(bottom, _width, _height, corner, sColor, 0.3);
        createBase(light, _width, _height, corner, gColor);
        light.filters = [blueGlow];
        createBase(base, _width, _height, corner, bColor);
        txt.x = -_width*0.5;
        txt.y = -_height*0.5;
        txt.width = _width;
        txt.height = _height - 1;
        txt.type = TextFieldType.DYNAMIC;
        txt.selectable = false;
        //txt.embedFonts = true;
        //txt.antiAliasType = AntiAliasType.ADVANCED;
        var tf:TextFormat = new TextFormat();
        tf.font = fontType;
        tf.size = 12;
        tf.align = TextFormatAlign.CENTER;
        txt.defaultTextFormat = tf;
        txt.text = label;
        enabled = true;
        mouseChildren = false;
    }
    private function rollOver(evt:MouseEvent):void {
        _over();
    }
    private function rollOut(evt:MouseEvent):void {
        _up();
    }
    private function press(evt:MouseEvent):void {
        _down();
    }
    private function release(evt:MouseEvent):void {
        _up();
    }
    private function click(evt:MouseEvent):void {
    }
    private function _up():void {
        txt.y = -_height*0.5;
        txt.textColor = upColor;
        base.y = -1;
        light.visible = false;
        light.y = -1;
    }
    private function _over():void {
        txt.y = -_height*0.5;
        txt.textColor = overColor;
        base.y = -1;
        light.visible = true;
        light.y = -1;
    }
    private function _down():void {
        txt.y = -_height*0.5 + 1;
        txt.textColor = overColor;
        base.y = 0;
        light.visible = true;
        light.y = 0;
    }
    private function _off():void {
        txt.y = -_height*0.5 + 1;
        txt.textColor = offColor;
        base.y = 0;
        light.visible = false;
        light.y = 0;
    }
    public function get clicked():Boolean {
        return _clicked;
    }
    public function set clicked(param:Boolean):void {
        _clicked = param;
        enabled = !_clicked;
        if (_clicked) {
            _down();
        } else {
            _up();
        }
    }
    public function get enabled():Boolean {
        return _enabled;
    }
    public function set enabled(param:Boolean):void {
        _enabled = param;
        buttonMode = _enabled;
        mouseEnabled = _enabled;
        useHandCursor = _enabled;
        if (_enabled) {
            _up();
            addEventListener(MouseEvent.MOUSE_OVER, rollOver, false, 0, true);
            addEventListener(MouseEvent.MOUSE_OUT, rollOut, false, 0, true);
            addEventListener(MouseEvent.MOUSE_DOWN, press, false, 0, true);
            addEventListener(MouseEvent.MOUSE_UP, release, false, 0, true);
            addEventListener(MouseEvent.CLICK, click, false, 0, true);
        } else {
            _off();
            removeEventListener(MouseEvent.MOUSE_OVER, rollOver);
            removeEventListener(MouseEvent.MOUSE_OUT, rollOut);
            removeEventListener(MouseEvent.MOUSE_DOWN, press);
            removeEventListener(MouseEvent.MOUSE_UP, release);
            removeEventListener(MouseEvent.CLICK, click);
        }
    }
    private function createBase(target:Shape, w:uint, h:uint, c:uint, color:uint, alpha:Number = 1):void {
        target.graphics.beginFill(color, alpha);
        target.graphics.drawRoundRect(-w*0.5, -h*0.5, w, h, c*2);
        target.graphics.endFill();
    }

}