/** 真ん中の円に触れるとドラムパターンと、トーンパターンが変わります。 */ 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(); } } Noise Instrument