forked from: forked from: forked from: Master-Melo-Ball
forked from forked from: forked from: Master-Melo-Ball (diff: 19)
------------------------------------------------- 操作説明: Aを入力 --------------------------------------------------- SiONのインポート
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/hWrT
*/
// forked from fukt's forked from: forked from: Master-Melo-Ball
// forked from sir4shumman's forked from: Master-Melo-Ball
// forked from sir4shumman's Master-Melo-Ball
/*-------------------------------------------------
操作説明:
Aを入力
---------------------------------------------------*/
package {
import flash.display.Sprite;
import flash.events.*;
import flash.geom.*;
//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;
private var py:Number;
//コンストラクタ
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@3v8o3rcrc;";
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(MouseEvent.CLICK,clickHandle)
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 = 16;
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{
private function clickHandle(event:MouseEvent):void {
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;
}
//音を鳴らす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 > 1){
soundStart();
}
}
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 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 _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(0xff0000,al);
this.graphics.drawRect(0, 0, 150, 150);
this.graphics.endFill();
radius = this.width/2
}
}