Beautifl - Flash Gallery

Thumbnail : Noise Instrument
Noise Instrument
enok 2010-11-03 MIT License

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

/**
真ん中の円に触れるとドラムパターンと、トーンパターンが変わります。
http://linktale.net/
*/

package {
    import com.flashdynamix.utils.SWFProfiler;
    import flash.display.Sprite; 

    [SWF(backgroundColor="0xffffff", frameRate="40")] 

    public class Trick extends Sprite { 
        public function Trick() { 
            //SWFProfiler.init(stage, this);
            Wonderfl.disable_capture();
            
            //ここのパラメータを変えると見た目が変わります。
            var trick:Sprite = new Kyu( this, stage.stageWidth / 2, stage.stageHeight / 2, 15, 2.5, 0x333333, 1, 2.0);
            addChild( trick );
        } 
    }
}

import flash.display.DisplayObjectContainer;
import flash.display.Sprite; 
import flash.events.Event;
import flash.events.MouseEvent;
import org.si.sion.effector.SiEffectSpeakerSimulator;
import org.si.sion.effector.SiEffectStereoChorus;
import org.si.sion.effector.SiEffectStereoDelay;
import org.si.sion.events.SiONTrackEvent;
import org.si.sion.sequencer.SiMMLTrack;
import org.si.sion.SiONDriver;
import org.si.sion.SiONVoice;
import org.si.sion.utils.SiONPresetVoice;
import org.si.sound.DrumMachine;

class Kyu extends Sprite {
    //const
    private const DEBUG:Boolean = true; //デバッグモード
    private const AROUND_NAMI_A:Number = 0.2;
    private const AROUND_NAMI_POS:Number = 0.3;
    
    //parent stage
    private var _w:Number;
    private var _h:Number;
    private var _centerX:Number;
    private var _centerY:Number;
    //main
    private var _namiColor:uint //波の色
    private var _cellW:int = 1; //セルの横幅
    private var _cellH:int = 1; //セルの縦幅
    private var _cellAmount:int; //セルの横位置
    private var _cellCnt:int; //セルの数
    private var _cellList:Array = new Array(); //セルリスト 
    private var _mouseArea:Number = 20.0;
    //nami
    private var _period:Number = 2.0; //周期T
    private var _aMin:Number = 0.0; //振幅の最小値(まるめ)
    private var _f:Number = 3.0; //振幅数
    private var _t:int = 1; //波時間
    private var _namiSpring:Number = 0.01; //ばね
    private var _namiFriction:Number = 0.8; //跳ね
    private var _upRate:Number;
    //kyu
    private var _kyuRadius:int = 150; //球の半径
    private var _kyuDefPos:Array = new Array(); //球のデフォルトポジション
    //count
    private var _loopCnt:int = 0; //loop回数
    //mouse
    private var _mousexNow:Number;
    private var _mouseyNow:Number;
    private var _mousexPre:Number;
    private var _mouseyPre:Number;
    //sion
    private var sionDriver:SiONDriver;
    private var drumMachine:DrumMachine;
    private var epianoVoice:SiONVoice;
    private var presetVoice:SiONPresetVoice;
    private var notes:Array;
    private var toneList:Array;
    private var toneNoList:Array;
    //button
    private var changeDrumMachineBtn:Sprite;
    
    public function Kyu( pStage:DisplayObjectContainer, pX:int, pY:int, pW:int, pH:int, pColor:uint, pAmount:int, pUpRate:Number ) {
        //stage
        _w = pStage.stage.stageWidth; 
        _h = pStage.stage.stageHeight; 
        _centerX = pX; 
        _centerY = pY;
        //nami
        _namiColor = pColor; 
        _cellW = pW;
        _cellH = pH; 
        _cellAmount = pAmount;
        _upRate = pUpRate;
        //kyu
        var kyuLength:int = 2 * Math.PI * _kyuRadius; 
        //cell
        _cellCnt = kyuLength / _cellAmount;
        //mouse
        _mousexNow = _mousexPre = _centerX;
        _mouseyNow = _mouseyPre = _centerY;
        
        initKyu();
        initSion();
        initButton();
    }
    
    private function initKyu():void {
        setCell();
        addEventListener( Event.ENTER_FRAME, loop );
    }
    
    private function initSion():void {
        // マトリックス各行に割り当てるノートを設定
        notes = [70, 67, 65, 60, 58, 55, 53, 48];
        
        // ドライバの生成
        sionDriver = new SiONDriver(2048);
        
        // ドラムマシンの生成
        drumMachine = new DrumMachine(
            Math.floor(Math.random() * 32),
            Math.floor(Math.random() * 18),
            Math.floor(Math.random() * 17),
            Math.floor(Math.random() * 5),
            Math.floor(Math.random() * 5),
            Math.floor(Math.random() * 3)
            );
        
        // エレクトリックピアノ音をプリセット音声リストから取得
        toneList = new Array("bass","bell","brass","guitar","lead","percus","piano","se","special","strpad","wind","world");
        toneNoList = new Array(54,18,20,18,42,38,20,1,5,25,8,7);
        
        presetVoice = new SiONPresetVoice();
        var no:uint = Math.floor(Math.random() * toneList.length);
        var tone:String = toneList[no];
        var tone_num:String = toneNoList[no];
        epianoVoice = presetVoice["valsound."+tone+tone_num];
        //trace("valsound." + tone + tone_num);
        
        // ビートイベントハンドラの設定
        sionDriver.setBeatCallbackInterval(1);
        sionDriver.addEventListener(SiONTrackEvent.BEAT, onBeat);
        
        // タイマ割り込みの設定
        //sionDriver.setTimerInterruption(1, _onTimerInterruption);
        
        // BPM の設定
        sionDriver.bpm = 70;
        
        // slot1 にエフェクタを設定する
        sionDriver.effector.initialize();
        sionDriver.effector.slot1 = [new SiEffectStereoChorus(), new SiEffectStereoDelay(500)];
        
        // ドライバの再生開始(エフェクトリセット無し)とリズム再生開始
        sionDriver.play(null, false);
        drumMachine.play();
    }
    
    private function initButton():void {
        var radius:Number = 50;
        changeDrumMachineBtn = new Sprite();
        changeDrumMachineBtn.graphics.beginFill(_namiColor);
        changeDrumMachineBtn.graphics.drawCircle(0, 0, radius);
        //changeDrumMachineBtn.graphics.drawEllipse(-_kyuRadius / rate / 2, -_kyuRadius / rate / 2 / 20, _kyuRadius / rate, _kyuRadius / rate / 20);
        changeDrumMachineBtn.graphics.drawRect(0, 0, 3, radius * 2);
        changeDrumMachineBtn.graphics.endFill();
        changeDrumMachineBtn.x = _centerX;
        changeDrumMachineBtn.y = _centerY;
        changeDrumMachineBtn.addEventListener(MouseEvent.ROLL_OVER, changeDrumMachineOver);
        changeDrumMachineBtn.addEventListener(MouseEvent.ROLL_OUT, changeDrumMachineOut);
        addChild(changeDrumMachineBtn);
    }
    
    private function changeDrumMachineOver(e:MouseEvent):void {
        var btn:Sprite = e.currentTarget as Sprite;
        btn.alpha = 0.85;
        
        sionDriver.stop();
        presetVoice = new SiONPresetVoice();
        var no:uint = Math.floor(Math.random() * toneList.length);
        var tone:String = toneList[no];
        var tone_num:String = toneNoList[no];
        epianoVoice = presetVoice["valsound."+tone+tone_num];
        //trace("valsound." + tone + tone_num);
        sionDriver.play(null, false);
        
        drumMachine.stop();
        drumMachine = new DrumMachine(
            Math.floor(Math.random() * 32),
            Math.floor(Math.random() * 18),
            Math.floor(Math.random() * 17),
            Math.floor(Math.random() * 5),
            Math.floor(Math.random() * 5),
            Math.floor(Math.random() * 3)
        );
        drumMachine.play();
    }
    
    private function changeDrumMachineOut(e:MouseEvent):void {
        var btn:Sprite = e.currentTarget as Sprite;
        btn.alpha = 1.0;
    }
    
    //セルをセット
    private function setCell():void {
        var cell:Cell;
        var x:Number, y:Number, dx:Number, dy:Number, angle:Number, rotation:Number;
        
        //セルの配置
        for (var i:uint = 0; i < _cellCnt; i++ ) {                
            //セルのデフォルト位置を定義
            cell = new Cell( _cellW, _cellH, _namiColor );
            //セルのバーチャル位置セット
            cell._x = i * _cellAmount;
            cell._y = _centerY;
            
            //球のデフォルト位状態をセット
            angle = Math.PI * 2 / _cellCnt * i - Math.PI / 2;
            x = _kyuRadius * Math.cos(angle) + _centerX;
            y = _kyuRadius * Math.sin(angle) + _centerY;
            dx = x - _centerX;
            dy = y - _centerY;
            angle = Math.atan2(dy, dx);
            rotation = ( angle - Math.PI / 2 ) * 180 / Math.PI;
            _kyuDefPos.push(new Array(x-cell._x, y-cell._y, x, y, rotation));
            
            //セル配置
            addChild(cell);
            _cellList.push(cell);
        }
    }
    
    private function onBeat(e:SiONTrackEvent):void {
        changeDrumMachineBtn.rotation += 4.5;
    }
    
    private function loop(e:Event):void {
        mouseSet();
        namiMove(); //描画
        
        _loopCnt++;
    }
    
    private function mouseSet():void {
        _mousexPre = _mousexNow;
        _mouseyPre = _mouseyNow;
        
        _mousexNow = mouseX;
        _mouseyNow = mouseY;
    }
    
    //波を動かす処理
    private function namiMove():void {
        var x:Number, y:Number, dx:Number, dy:Number, dist:Number ,angle:Number;
        
        for (var i:uint = 0; i < _cellCnt; i++ ) {
            dx = _cellList[i].x - _kyuDefPos[i][2];
            dy = _cellList[i].y - _kyuDefPos[i][3];
            dist = Math.sqrt( dx * dx + dy * dy );
                
            if ( Math.abs(_cellList[i]._a) <= AROUND_NAMI_A && dist <= AROUND_NAMI_POS) {
                //丸め処理
                _cellList[i].x = _kyuDefPos[i][2];
                _cellList[i].y = _kyuDefPos[i][3];
                _cellList[i]._a = 0;
            }else {
                //定常波の方程式
                y = _cellList[i]._a * Math.sin( _t / _period - i * _cellAmount / _f );
                
                angle = _kyuDefPos[i][4] * Math.PI / 180 - Math.PI / 2;
                x = Math.cos(angle) * y;
                y = Math.sin(angle) * y;
                
                y += _centerY;
                _cellList[i]._vx = _cellList[i]._x + x;
                _cellList[i]._vy = y; //描画
                
                //加速度をばねる
                springA(_cellList[i]); //振幅を変化

                //一時変換
                _cellList[i].x = _cellList[i]._vx + _kyuDefPos[i][0];
                _cellList[i].y = _cellList[i]._vy + _kyuDefPos[i][1];
                _cellList[i].rotation = _kyuDefPos[i][4];

            }
                            
            //マウスチェック
            //addMouseValue(_cellList[i]);
            checkWave( i, mouseX, mouseY, _upRate );
        }
        _t++; //波時間を進める
    }
    
    //波の振幅をばねで計算
    private function springA( pCell:Cell ):void {
        var dx:Number, ax:Number;
        
        dx = _aMin - pCell._a;
        ax = dx * _namiSpring;
        pCell._avx += ax;
        pCell._avx *= _namiFriction;
        pCell._a += pCell._avx;
    }
    
    private function addMouseValue( pCell:Cell ):void{
        var dx:Number, dy:Number, dist:Number, per:Number;
        
        dx = pCell.x - _mousexNow;
        dy = pCell.y - _mouseyNow;
        dist = Math.sqrt( dx * dx + dy * dy );
        per = ( _w - dist ) / _w;
        
        pCell._a += (_mousexNow - _mousexPre) * per * 0.1;
    }
    
    //マウスチェック
    private function checkWave(pI:int, pTargetX:Number, pTargetY:Number, namiRate:Number ):void {
        var dx:Number = _cellList[pI].x - pTargetX;
        var dy:Number = _cellList[pI].y - pTargetY;
        var dist:Number = Math.sqrt( dx * dx + dy * dy );
        
        if (dist < _mouseArea) {
            wavePattern(pI, namiRate);
        }
    }
    
    //波パターン
    private function wavePattern(pI:int, upRate:Number):void {
        var i:uint, y:Number;
        var startI:int = pI - 100; if (startI < 0) { startI = 0; }
        var endI:int =  pI + 100; if (endI > _cellCnt) { endI = _cellCnt; }
        var dist:Number;
        
        for (i = startI; i < endI; i++) {
            dist = Math.abs((pI - i)); if (dist == 0) { dist = 1.0; }
            y = 1 / dist * upRate;
            _cellList[i]._a += y;
        }
        
        if (_loopCnt % 6 == 0) {
            //0~127
            var note:int = 127 - Math.floor((pI / _cellList.length) * 127);
            var track:SiMMLTrack;
            track = sionDriver.noteOn(note, epianoVoice, 1);
            track.velocity = 5;
            track.effectSend1 = 48;
        }
    }
}

import flash.display.Sprite;

class Cell extends Sprite {
    public var _x:Number = 0;
    public var _y:Number = 0;
    public var _vx:Number = 0;
    public var _vy:Number = 0;
    public var _w:int = 0;
    public var _h:int = 0;
    public var _rotaion:Number = 0;
    public var _color:int = 0;
    public var _a:Number = 0.0; //振幅
    public var _avx:Number = 0.0; //振幅の速度
    
    public function Cell( pW:Number = 1, pH:Number = 1, pColor:uint = 0x000000 ) {
        _w = pW;
        _h = pH;
        _color = pColor;
        
        graphics.beginFill(_color); 
        graphics.drawRect( -_w / 2, 0, _w, _h);
        graphics.endFill();
    }        
}