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

forked from: 万華鏡+mp3再生

kaleidoscope + sound spectrum
* 万華鏡 + サウンドスペクトル表示
* 
* 左がオレンジ、右が青
* 重い・・・。要軽量化
* 
* ♪使用音楽素材について♪
* 音楽素材/魔王魂(http://maoudamashii.jokersounds.com/)の素材を使わせていただきました。
* ありがとうございます。
*
/**
 * Copyright takishiki ( http://wonderfl.net/user/takishiki )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/1Do1
 */

// forked from takishiki's 万華鏡+mp3再生
/*
 * kaleidoscope + sound spectrum
 * 万華鏡 + サウンドスペクトル表示
 * 
 * 左がオレンジ、右が青
 * 重い・・・。要軽量化
 * 
 * ♪使用音楽素材について♪
 * 音楽素材/魔王魂(http://maoudamashii.jokersounds.com/)の素材を使わせていただきました。
 * ありがとうございます。
 * 
 */

package 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.display.BlendMode;
    import flash.display.Graphics;
    import flash.filters.GlowFilter;
    import flash.system.Security;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.media.SoundLoaderContext;
    import flash.media.SoundTransform;
    import flash.media.SoundMixer;
    import flash.net.URLRequest;
    import flash.utils.ByteArray;
    
    
    [SWF(width = 465, height = 465, frameRate = 30, backgroundColor = 0x000000)]
    public class Main extends MovieClip 
    {
        // 定数
        private const FFT_MODE        :Boolean = false;
        private const POLY_R        :int = 50;
        // 変数
        private var _sp:Sprite;
        private var _bmp:Bitmap;
        private var _bmpd:BitmapData;
        private var _deg:Number = 0;
        private var _bgSp:Sprite;
        private var _canvas:Sprite;
        private var _mainSp:Sprite;
        private var _end:Boolean;
        
        private var _chips:Array;
        
        private var _cnt:int;
        
        // constructor
        public function Main():void {
            stage.frameRate = 30;
            
            _cnt = 0;
            _end = false;
            
            _chips = [];
            _mainSp = new Sprite();
            _canvas = new Sprite();    // 星描画用
            _mainSp.addChild(_canvas);
            
            var g:Graphics;
            // 三角形描画
            var sp:Sprite = new Sprite();
            g = sp.graphics;
            g.beginFill(0x000000, 1.0);
            g.drawRect(0, 0, POLY_R * 2, POLY_R * 2);
            drawPoly(sp, 3, POLY_R, POLY_R, POLY_R, 30);
            g.endFill();
            _mainSp.addChild(sp);
            
            _bmpd = new BitmapData(stage.stageWidth * 2, stage.stageHeight * 2, false, 0x000000);
            _bmp = new Bitmap(_bmpd);
            _bmp.x = -(stage.stageWidth * 2) / 2;
            _bmp.y = -(stage.stageHeight * 2) / 2;
            _sp = new Sprite();
            _sp.addChild(_bmp);
            _sp.x = stage.stageWidth / 2;
            _sp.y = stage.stageHeight / 2;
            this.addChild(_sp);
            
            // mp3
            var snd:Sound = new Sound();
            Security.loadPolicyFile("http://mutast.heteml.jp/crossdomain.xml");
            var req:URLRequest;
            req = new URLRequest("http://vaindog.raindrop.jp/wonderfl/sound/bgm_maoudamashii_cyber06.mp3");
            var context:SoundLoaderContext = new SoundLoaderContext(10, true);
            snd.load(req,context);
            
            var channel:SoundChannel;
            channel = snd.play();
            var transform:SoundTransform = new SoundTransform();
            transform.volume = 0.5;
            transform.pan = 0.0;
            channel.soundTransform = transform;
            
            channel.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete);
            
            this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
        
        // 多角形描画
        private function drawPoly(sp:Sprite, num:int, x:int, y:int, r:int, deg:Number):void {
            /*
             * sp:対象Sprite
             * num:頂点の数
             * x:中心のx座標
             * y:中心のy座標
             * r:半径
             * deg:回転角度(度)
             */
            var g:Graphics = sp.graphics;
            var rad:Number;
            var i:int;
            var step:Number = 360 / num;
            
            // 描画スタート位置に移動
            rad = deg2rad(0 + deg);
            g.moveTo(x + r * Math.cos(rad), y + r * Math.sin(rad));
            for (i = 0; i < num; i++) {
                rad = deg2rad((i + 1) * step + deg);
                g.lineTo(x + r * Math.cos(rad), y + r * Math.sin(rad));
            }
        }
        
        //
        private function onPlaybackComplete(event:Event):void {
            _end = true;
            //removeEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
        
        // フレーム処理
        private function onEnterFrame(event:Event):void {
            _sp.rotation += 1;
            
            // 万華鏡画像作成
            makeImage(_bmpd);
            
            _cnt++;
            if(_cnt<10) {
                return;
            }
            _cnt = 0;
            
            // sound
            var bytes:ByteArray = new ByteArray();
            const CHANNEL_LENGTH:int = 256;
            
            SoundMixer.computeSpectrum(bytes, FFT_MODE, 0);
            
            var maxL:Number = 0;
            var maxR:Number = 0;
            var chip:Chip;
            
            var i:int;
            // L
            for (i = 0; i < CHANNEL_LENGTH; i++) {
                maxL = Math.max(bytes.readFloat(), maxL);
            }
            chip = new Chip(POLY_R, -30, 1 * Math.cos(Math.PI / 6 * (1 - maxL)), 1 * Math.sin(Math.PI / 6 * (1 - maxL)), 20 * maxL, randRange(0, 359), hsv2rgb(30, 1, 1));
            _canvas.addChild(chip);
            _chips.push(chip);
            
            // R
            for (i = CHANNEL_LENGTH; i > 0; i--) {
                maxR = Math.max(bytes.readFloat(), maxR);
            }
            chip = new Chip(POLY_R, -30, 1 * Math.cos(Math.PI / 6 * (1 - maxR)), -1 * Math.sin(Math.PI / 6 * (1 - maxR)), 20 * maxR, randRange(0, 359), hsv2rgb(200, 1, 1));
            _canvas.addChild(chip);
            _chips.push(chip);
            
            
            // チップ生存チェック
            var end_y:Number = POLY_R * 2 + 30;
            var len:int = _chips.length;
            for (i = 0; i < len; i++) {;
                if (_chips[i].y >= end_y) {
                    _canvas.removeChild(_chips[i]);
                    _chips.splice(i, 1);
                    len = len - 1;
                }
            }
            
            if ((_end) && (_chips.length==0)) {
                this.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
            }
        }
        
        // 万華鏡画像作成
        private function makeImage(target:BitmapData):void {
            var h:int = POLY_R * 3 / 2;
            var r3:Number = Math.sqrt(3);
            
            // ステージ用
            var bmpd:BitmapData = new BitmapData(POLY_R * 2, POLY_R * 2, false, 0x000000);
            // 元の三角形用
            var bmpdTri:BitmapData = new BitmapData(POLY_R * 2, POLY_R * 2, false, 0x000000);
            // 一行描画用
            var bmpdRow:BitmapData = new BitmapData(target.width, Math.ceil(h), false, 0x000000);
            
            // ステージ描画
            bmpd.lock();
            bmpd.draw(_mainSp);
            bmpd.unlock();
            
            var rect:Rectangle = new Rectangle();
            rect.x = 0;
            rect.y = 0;
            rect.width = POLY_R * 2;
            rect.height = POLY_R * 2;
            
            // 三角形部分を切り取り
            bmpdTri.copyPixels(bmpd, rect, new Point());
            
            var matrix:Matrix = new Matrix();
            var matrix2:Matrix = new Matrix();
            var rad:Number = Math.PI  * 2 / 3;    // 120°
            var num:int;
            var i:int;
            
            // 行作成
            bmpdRow.lock();
            num = Math.ceil(target.width / POLY_R) + 2;
            for (i = 0; i < num; i++) {
                matrix = new Matrix();
                
                // 中央に平行移動
                matrix2 = new Matrix();
                matrix2.translate( -POLY_R, -POLY_R);
                matrix.concat(matrix2);
                
                if (i % 2 == 0) {
                    // 偶数
                    
                    // 回転
                    matrix2 = new Matrix();
                    matrix2.rotate(-rad * i);
                    matrix.concat(matrix2);
                    
                }else {
                    // 奇数
                    
                    // 反転
                    matrix2 = new Matrix();
                    matrix2.scale(1, -1);
                    matrix.concat(matrix2);
                    
                    // 回転
                    matrix2 = new Matrix();
                    matrix2.rotate(-rad * int(i / 2) + rad);
                    matrix.concat(matrix2);
                    
                    // y軸平行移動
                    matrix2 = new Matrix();
                    matrix2.translate(0,  -POLY_R / 2);
                    matrix.concat(matrix2);
                }
                
                // x軸平行移動
                matrix2 = new Matrix();
                matrix2.translate(Math.floor(i * POLY_R / 2 * r3), 0);
                matrix.concat(matrix2);
                
                // 基準位置まで平行移動
                matrix2 = new Matrix();
                matrix2.translate(0, POLY_R);
                matrix.concat(matrix2);
                
                // 描画
                bmpdRow.draw(bmpdTri, matrix, new ColorTransform(), BlendMode.LIGHTEN);
            }
            bmpdRow.unlock();
            
            
            // 行のbmpdを反転しながら列方向に描画
            target.lock();
            // 背景色で塗りつぶし
            target.fillRect(target.rect, 0x000000);
            
            num = Math.ceil(target.height / POLY_R);
            for (i = 0; i < num; i++) {
                matrix = new Matrix();
                
                // 中央に平行移動
                matrix2 = new Matrix();
                matrix2.translate(0, -Math.round(h / 2));
                matrix.concat(matrix2);
                
                if (i % 2 == 1) {
                    // 奇数
                    // 反転
                    matrix2 = new Matrix();
                    matrix2.scale(1, -1);
                    matrix.concat(matrix2);
                }
                
                // 平行移動
                matrix2 = new Matrix();
                matrix2.translate(0, Math.floor(h * i));
                matrix.concat(matrix2);
                
                // 基準位置まで平行移動
                matrix2 = new Matrix();
                matrix2.translate(0, Math.round(h / 2));
                matrix.concat(matrix2);
                
                // 描画
                target.draw(bmpdRow, matrix, new ColorTransform(), BlendMode.LIGHTEN);
            }
            target.unlock();
            
            bmpdTri.dispose();
            bmpdRow.dispose();
        }
        
        // HSV -> RGB(uint)
        private function hsv2rgb(h:Number, s:Number, v:Number):uint {
            var r:Number = 0;
            var g:Number = 0;
            var b:Number = 0;
            
            if (s == 0) {
                r = g = b = v;
            }else {
                var hTemp:Number = (h + 360) % 360;
                hTemp /= 60;
                var i:Number = Math.floor(hTemp);   // 整数部
                var f:Number = hTemp - i;    // 小数部
                
                var p:Number = v * (1.0 - s);
                var q:Number = v * (1.0 - (s * f));
                var t:Number = v * (1.0 - (s * (1.0 - f)));
                
                switch(i) {
                    case 0:
                        r = v;
                        g = t;
                        b = p;
                        break;
                    case 1:
                        r = q;
                        g = v;
                        b = p;
                        break;
                    case 2:
                        r = p;
                        g = v;
                        b = t;
                        break;
                    case 3:
                        r = p;
                        g = q;
                        b = v;
                        break;
                    case 4:
                        r = t;
                        g = p;
                        b = v;
                        break;
                    case 5:
                        r = v;
                        g = p;
                        b = q;
                        break;
                }
            }
            return rgb2hex(r * 255, g * 255, b * 255);
        }
        
        // R, G, B -> hex color value
        private function rgb2hex(r:Number = 0, g:Number = 0, b:Number = 0):uint {
            r = Math.round(r);
            g = Math.round(g);
            b = Math.round(b);
            return 0xff000000 + r * 0x10000 + g * 0x100 + b;
        }
        
        // degree -> radian
        private function deg2rad(deg:Number):Number {
            deg %= 360;
            return deg / 180 * Math.PI;
        }
        
        // a-bの乱数生成
        private function randRange(min:Number = 0, max:Number = 1):Number {
            var randomNum:Number = Math.floor(Math.random() * (max - min + 1)) + min;
            return randomNum;
        }
    }
}

// Chip
import flash.display.*;
import flash.events.Event;
import flash.filters.GlowFilter;

class Chip extends Sprite {
    private var _vx:Number;
    private var _vy:Number;
    private var _r:Number;
    private var _deg:Number;
    private var _color:uint;
    
    // 
    public function Chip(x:Number, y:Number, vy:Number, vx:Number, r:Number, deg:Number, color:uint):void {
        this.x = x;
        this.y = y;
        
        this.rotation = deg;
        _vy = vy;
        _vx = vx;
        _r = r;
        _color = color;
        _deg = randRange(0, 20) - 10;
        
        var alpha:Number = randRange(0, 100) / 100;
        var g:Graphics = this.graphics;
        g.lineStyle(1, _color, 1.0);
        //g.beginFill(_color, alpha);
        drawStar(this, 5, 0, 0, _r, _r * 0.5, 0);
        g.endFill();
        this.filters = [new GlowFilter(_color, 0.8, 10, 10, 2, 2, true, false), new GlowFilter(_color, 0.6, 20, 20, 4, 2, false, false)];
        
        this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }
    
    // 
    private function onEnterFrame(event:Event):void {
        this.y += _vy;
        this.x += _vx;
        this.rotation += _deg;
    }
    
    // draw star shape
    private function drawStar(sp:Sprite, num:int, x:int, y:int, r1:int, r2:int, deg:Number):void {
        /*
        * sp:対象Sprite
        * num:頂点の数
        * x:中心のx座標
        * y:中心のy座標
        * r1:外側(山)の半径
        * r2:内側(谷)の半径
        * deg:回転角度(度)
        */
        var g:Graphics = sp.graphics;
        var rad:Number;
        var i:int;
        var step:Number = 360 / num;
        
        // 描画スタート位置に移動
        rad = deg2rad(0 + deg);
        g.moveTo(x + r1 * Math.cos(rad), y + r1 * Math.sin(rad));
        // 谷 -> 山 -> 谷 の順番で線を描画
        for (i = 0; i < num; i++) {
            rad = deg2rad(i * step + deg + step / 2);
            g.lineTo(x + r2 * Math.cos(rad), y + r2 * Math.sin(rad));
            rad = deg2rad((i + 1) * step + deg);
            g.lineTo(x + r1 * Math.cos(rad), y + r1 * Math.sin(rad));
        }
    }
    
    // a-bの乱数生成
    private function randRange(min:Number = 0, max:Number = 1):Number {
        var randomNum:Number = Math.floor(Math.random() * (max - min + 1)) + min;
        return randomNum;
    }
    
    // degree -> radian
    private function deg2rad(deg:Number):Number {
        deg %= 360;
        return deg / 180 * Math.PI;
    }
}