forked from: forked from: forked from: Master-Melo-Ball

by fukt forked from forked from: forked from: Master-Melo-Ball (diff: 250)
-------------------------------------------------
操作説明:
Aを入力
---------------------------------------------------

SiONのインポート
♥0 | Line 307 | Modified 2010-10-26 07:28:29 | MIT License
play

ActionScript3 source code

/**
 * Copyright fukt ( http://wonderfl.net/user/fukt )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wPhR
 */

// forked from sir4shumman's forked from: forked from: Master-Melo-Ball
/*-------------------------------------------------
操作説明:
Aを入力
---------------------------------------------------*/
package {
    import flash.display.Sprite;
    import flash.events.*;
    import flash.geom.*;
    import flash.ui.Keyboard;
    import flash.text.TextField;
    import flash.display.DisplayObjectContainer;
    //SiONのインポート
    import org.si.sion.*;
    import org.si.sion.events.*;
    import org.si.sion.effector.*;
    import org.si.sion.utils.SiONPresetVoice;
    import org.si.sion.sequencer.SiMMLTrack;
    import org.si.sion.utils.Scale;
    import org.si.sound.Arpeggiator;

    
    [SWF(backgroundColor="#FFFFFF",width='600',height='600', frameRate=60)]

    public class MeloBall extends Sprite {

    // driver
    private var driver:SiONDriver = new SiONDriver();
// preset voice
        private var presetVoice:SiONPresetVoice = new SiONPresetVoice();

     // MML data
    //private var part:Array;
    public var rythmLoop:SiONData;

    private var sw:Boolean = false;

    // arpeggiator
    public var arpeggiator:Arpeggiator;

    // Stage Const
    private var centerX:Number = stage.width/2;
    private var centerY:Number = stage.height/2;
    
    // ボールの数
        private var numBalls:uint = 0;
        //係数
    private var bounce:Number = -1.0;
    //ボールの参照を入れる配列
    private var balls:Array = new Array();
    //ボールのアルファ値
    private var xalpha:Number = 0.7;
    //速度係数
    private var velocity:Number = 1;//ここに速度を入れる
    //半径
    private var radius:Number = 25;
    
    private var px:Number=0;
    private var py:Number=0;
    private var dvx:Number; //x速度プロパティ宣言
    private var dvy:Number; //y速度プロパティ宣言
    private     var Bl:Sprite = new Sprite();

    


//コンストラクタ
        public function MeloBall() {
        //soundStart();

       // compile mml.
        var mml:String = "t110;";
        mml += "%6@0o3l8$c2cc.c.;";
        mml += " %6@1o3$rcrc;";
        mml += "%6@2v8l8$crccrrcc;";
        mml += "%6@3v8o3$rcrc;";
        mml += "%6@4v8l16o4$[c.c.c]2 >b.b.b <c.c.c;";
        rythmLoop = driver.compile(mml);

        // set voices of "%6@0-4" from preset
        rythmLoop.setVoice(0, presetVoice["valsound.percus1"]);
        rythmLoop.setVoice(1, presetVoice["valsound.percus28"]);
        rythmLoop.setVoice(2, presetVoice["valsound.percus17"]);
        rythmLoop.setVoice(3, presetVoice["valsound.percus23"]);
        rythmLoop.setVoice(4, presetVoice["valsound.bass3"]);
       
       
        stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDownHandle)
        
        addChild(Bl);
        Bl.graphics.beginFill(0xFFCC00);
        Bl.graphics.drawCircle(5, 5, 10);
        Bl.height = 40;
        Bl.width = 40;
        Bl.x = Math.random() * 600;    // 初期x座標
        Bl.y = Math.random() * 600;    // 初期y座標
        dvx = (Math.random() * 2 - 1) * 5;      // x方向移動量
        dvy = (Math.random() * 2 - 1) * 5;      // y方向移動量
        addEventListener(Event.ENTER_FRAME, Move);
        
            arpeggiator = new Arpeggiator(new Scale("jap"), 1, [0,1,4,0,5,4,2,1]);
            arpeggiator.voice = presetVoice["valsound.lead32"];
            //arpeggiator.portament = 16;
            arpeggiator.volume = 0.3;
            arpeggiator.noteQuantize = 8;
            arpeggiator.pattern = [0,1,4,0,5,4,2,1];
            //driver.setTimerInterruption(4, note);
            driver.setTimerInterruption(16, _onTimerInterruption);

        // SiONイベントトリガー用のイベントリスナーを設定
            driver.addEventListener(SiONTrackEvent.NOTE_ON_STREAM,  _onNoteOn);
            driver.addEventListener(SiONTrackEvent.NOTE_OFF_STREAM, _onNoteOff);
            driver.addEventListener(SiONEvent.STREAM, onStreamHandler);
        driver.play(rythmLoop);
        }

        
private function  KeyDownHandle(e:KeyboardEvent):void{

  addEventListener(Event.ENTER_FRAME, enterFrameHandler);
           stage.addEventListener(MouseEvent.CLICK, clickHandler);

  //  stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);

    if(e.keyCode == 65 ) CreateBall(1);
    else if(e.keyCode == 66 ) CreateBall(2);
    else if(e.keyCode == 67 ) CreateBall(3);
    else if(e.keyCode == 68 ) CreateBall(4);
    else if(e.keyCode == 69 ) CreateBall(5);
    else if(e.keyCode == 70 ) CreateBall(6);
    else if(e.keyCode == 71 ) CreateBall(7);
    else if(e.keyCode == 72 ) CreateBall(8);
    else if(e.keyCode == 73 ) CreateBall(9);
    else if(e.keyCode == 74 ) CreateBall(10);

    }


private function CreateBall(n:uint):void{

var ball:Ball = new Ball(radius,Math.random()*0xffffff,xalpha);
    ball.mass = radius;
    ball.x = Math.random() * 600;
    ball.y = Math.random() * 600;
    ball.vx = (Math.random() * 10 - 5) * velocity; 
    ball.vy = (Math.random() * 10 - 5) * velocity;
    addChild(ball);
    balls.push(ball);//参照を格納
    numBalls += 1;//ボールの数を更新

    //if(numBalls == 1){driver.sequenceOn(bass,null,0,0,2,0,true)}
    //else if(numBalls == 2){driver.sequenceOn(bass,null,0,0,2,0,true)}

}

private function onEnterFrame(event:Event):void {

    for (var i:uint = 0; i < numBalls; i++) {
    var ball:Ball = balls[i];
    ball.x += ball.vx;
    ball.y += ball.vy;
    checkWalls(ball,i);
    }

    for (i = 0; i < numBalls; i++) {
    var ballA:Ball = balls[i];
        if(numBalls > 1){
        for (var j:Number = i + 1; j < numBalls; j++) {
            var ballB:Ball = balls[j];
            checkCollision(ballA, ballB);
            }
        }
    }
}

//壁に当たったときの処理    
private function checkWalls(ball:Ball,i:uint):void {
    if (ball.x + ball.radius > stage.stageWidth) {
        ball.x = stage.stageWidth - ball.radius;
         ball.vx *= bounce;
        } else if (ball.x - ball.radius < 0) {
        ball.x = ball.radius;
        ball.vx *= bounce;
        }
         if (ball.y + ball.radius > stage.stageHeight) {
        ball.y = stage.stageHeight - ball.radius;
         ball.vy *= bounce;
        } else if (ball.y - ball.radius < 0) {
        ball.y = ball.radius;
        ball.vy *= bounce;
         }
    }


//それぞれのボールが衝突しているかどうかチェック
    private function checkCollision(ball0:Ball, ball1:Ball):void {
        var dx:Number = ball1.x - ball0.x;
        var dy:Number = ball1.y - ball0.y;
        var dist:Number = Math.sqrt(dx*dx + dy*dy);
        if (dist < ball0.radius + ball1.radius) {
         note(ball0.x,ball0.y);

        if(sw == false){
        sw = true;
         //driver.noteOn(100,null,0.5,0,0,0,0,0,0,true);
        }else{
         sw = false;
         }

//衝突スイッチ//
    var angle:Number = Math.atan2(dy, dx);
    var cos:Number = Math.cos(angle);
    var sin:Number = Math.sin(angle);

    var pos0:Point = new Point(0, 0);
    var pos1:Point = rotate(dx, dy, sin, cos, true);
    var vel0:Point = rotate(ball0.vx, ball0.vy, sin, cos, true);
    var vel1:Point = rotate(ball1.vx, ball1.vy, sin, cos, true);

    var vxTotal:Number = vel0.x - vel1.x;
    vel0.x = ((ball0.mass - ball1.mass) * vel0.x +
    2 * ball1.mass * vel1.x) /
    (ball0.mass + ball1.mass);
    vel1.x = vxTotal + vel0.x;

    var absV:Number = Math.abs(vel0.x) + Math.abs(vel1.x);
    var overlap:Number = (ball0.radius + ball1.radius)
    - Math.abs(pos0.x - pos1.x);
    pos0.x += vel0.x / absV * overlap;
    pos1.x += vel1.x / absV * overlap;

    var pos0F:Object = rotate(pos0.x, pos0.y, sin, cos, false);
    var pos1F:Object = rotate(pos1.x, pos1.y, sin, cos, false);

    //注意!ball1を先に計算しないと、エラー発生
    ball1.x = ball0.x + pos1F.x;
    ball1.y = ball0.y + pos1F.y;
    ball0.x = ball0.x + pos0F.x;
    ball0.y = ball0.y + pos0F.y;

    var vel0F:Object = rotate(vel0.x, vel0.y, sin, cos, false);
    var vel1F:Object = rotate(vel1.x, vel1.y, sin, cos, false);

    ball0.vx = vel0F.x;
    ball0.vy = vel0F.y;
    ball1.vx = vel1F.x;
    ball1.vy = vel1F.y;
    }
}


//計算できるように回転させる動作
private function rotate(x:Number, y:Number, sin:Number, cos:Number, reverse:Boolean):Point {

    var result:Point = new Point();
    if (reverse) {
    result.x = x * cos + y * sin;
    result.y = y * cos - x * sin;
    } else {
    result.x = x * cos - y * sin;
    result.y = y * cos + x * sin;
    }
    return result;
}


private function Move(e:Event):void    {
//速度を加算
Bl.x += dvx;
Bl.y += dvy;
//壁当たり判定
if(Bl.x < 0 + Bl.width/2){  
//driver.noteOn(72,null,1,0,0,0,0,0,0,true);
Bl.x = 0 + Bl.width/2;
dvx *= -1;
}
if(Bl.x > 465 - Bl.width/2){
//driver.noteOn(76,null,1,0,0,0,0,0,0,true);
Bl.x = 465 - Bl.width/2;
dvx *= -1;
}
if(Bl.y < 0 + Bl.height/2){
//driver.noteOn(79,null,1,0,0,0,0,0,0,true);
Bl.y = 0 + Bl.height/2;
dvy *= -1;
}
if(Bl.y > 465 -Bl.height/2){
//driver.noteOn(83,null,1,0,0,0,0,0,0,true);
Bl.y = 465 - Bl.height/2;
dvy *= -1;
}
}

private function oonEnterFrame(event:Event):void {    
    if(numBalls > 1){
    for (var j:Number = 1; j < numBalls; j++) {
        var ballC:Ball = balls[j];
        }
    }
}

    
//それぞれのボールが衝突しているかどうかチェック
private function mblcheckCollision(Bl:Ball, ball1:Ball):void {
        var dx:Number = ball1.x - Bl.x;
        var dy:Number = ball1.y - Bl.y;
        var dist:Number = Math.sqrt(dx*dx + dy*dy);
        if (dist < Bl.radius + ball1.radius) {
         note(Bl.x,Bl.y);

        if(sw == false){
        sw = true;
         //driver.noteOn(100,null,0.5,0,0,0,0,0,0,true);
        }else{
         sw = false;
         }
         
//衝突スイッチ//
    var angle:Number = Math.atan2(dy, dx);
    var cos:Number = Math.cos(angle);
    var sin:Number = Math.sin(angle);

    var pos0:Point = new Point(0, 0);
    var pos1:Point = rotate(dx, dy, sin, cos, true);
    var vel0:Point = rotate(Bl.vx, Bl.vy, sin, cos, true);
    var vel1:Point = rotate(ball1.vx, ball1.vy, sin, cos, true);

    var vxTotal:Number = vel0.x - vel1.x;
    vel0.x = ((Bl.mass - ball1.mass) * vel0.x +
    2 * ball1.mass * vel1.x) /
    (Bl.mass + ball1.mass);
    vel1.x = vxTotal + vel0.x;

    var absV:Number = Math.abs(vel0.x) + Math.abs(vel1.x);
    var overlap:Number = (Bl.radius + ball1.radius)
    - Math.abs(pos0.x - pos1.x);
    pos0.x += vel0.x / absV * overlap;
    pos1.x += vel1.x / absV * overlap;

    var pos0F:Object = rotate(pos0.x, pos0.y, sin, cos, false);
    var pos1F:Object = rotate(pos1.x, pos1.y, sin, cos, false);

    //注意!ball1を先に計算しないと、エラー発生
    ball1.x = Bl.x + pos1F.x;
    ball1.y = Bl.y + pos1F.y;
    Bl.x = Bl.x + pos0F.x;
    Bl.y = Bl.y + pos0F.y;

    var vel0F:Object = rotate(vel0.x, vel0.y, sin, cos, false);
    var vel1F:Object = rotate(vel1.x, vel1.y, sin, cos, false);

    Bl.vx = vel0F.x;
    Bl.vy = vel0F.y;
    ball1.vx = vel1F.x;
    ball1.vy = vel1F.y;
    }
}



//音を鳴らす16×16の音
private function note(x:Number,y:Number):void{
//driver.noteOn(100,null,4,4,0,0,0,0,0,true);
}


//ノートオン時の効果処理
    private function _onNoteOn(e:SiONTrackEvent) : void {
    
    for (var i:uint = 0; i < numBalls; i++) {
        var ball:Ball = balls[i];
        ball.graphics.beginFill(Math.random()*0xffffff); 
        //ball.graphics.endFill();
        //ball.width = 100;
        //ball.height = 60;
        }
    }

    private function _onTimerInterruption():void{
    if(numBalls > 0){driver.sequenceOn(rythmLoop,null,0,0,0,0,true);}
    if(numBalls == 2){
    soundStart();
        }
    }


    private function setPxPy():void{
        if( numBalls == 2){
            var ball:Ball;

        px = ball.x / 465;
        py = ball.y / 465;
        if(px<0)px=0;
        if(px>0.9)px=0.9;
        if(py<0)py=0;
        if(py>0.9)py=0.9;
        }
    }

private function onStreamHandler(e:SiONEvent):void {
// update arpeggiator pitch and length
setPxPy();
arpeggiator.scaleIndex = px * 40;
arpeggiator.noteLength = [2,2,2,2,2,2,2,2][int(py * 4 + 0.99)];
}

public function soundStart():void {
setPxPy();
arpeggiator.scaleIndex = px * 40;
arpeggiator.noteLength = [2,2,2,2,2,2,2,2][int(py * 4 + 0.99)];
// start arpeggio
arpeggiator.play();
}


private function _onNoteOff(e:SiONTrackEvent) : void {

for (var i:uint = 0; i < numBalls; i++) {
    var ball:Ball = balls[i];
    //ball.width = 50;
    //ball.height = 50;
    }
}
}
}

/*-------------------------------------
パッケージ外クラス定義
 ---------------------------------------*/

import flash.display.*;
class Ball extends Sprite
{
    public var vx:Number;
    public var vy:Number;
    public var mass:Number;
    public var radius:Number;
    //rd=半径、cl=色、al=アルファ値
    function Ball(rd:Number,cl:Number,al:Number)
    {

        this.graphics.beginFill(cl,al);
        this.graphics.drawCircle(0, 0, rd);
        this.graphics.endFill();
        radius = this.width/2 

    }
}