Beautifl - Flash Gallery

Thumbnail : SoundBall
SoundBall
osamX 2010-07-14 MIT License

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

// forked from gaina's soundtest6
/**
 * 参考:
 *  QuickBox2D はじめの第一歩			http://blog.alumican.net/2009/06/28_021753
 *  QuickBox2D オブジェクトの平行移動と回転	http://blog.alumican.net/2009/07/06_014321
 *  flash on 2010-3-15 				http://wonderfl.net/c/uMNq
 *  おくれてきたおのまとぺ					http://wonderfl.net/c/1a5I
 *  Puppyish Pentatonicism			http://wonderfl.net/c/toV4
 */
package 
{
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundLoaderContext;
	import flash.media.SoundMixer;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	import com.actionsnippet.qbox.*;
	
	public class Main extends Sprite {
		private static const SIZE:int = 465;
		private static const QBSIZE:Number = SIZE / 30;
		private static const PATH:String = "http://www.takasumi-nagai.com/soundfiles/sound001.mp3";
		private static const CH:uint = 256;
		private static const BALL:uint = 6;	//ボールの個数
		
		private var _snd:Sound;
        private var _sndCh:SoundChannel;
        private var _ba:ByteArray;
		
		private var _leftBallArr:Array = [], _rightBallArr:Array = [];
		private var _leftBoxArr:Array = [],  _rightBoxArr:Array = [];
		
		public function Main():void {
			Wonderfl.capture_delay(3);
			graphics.beginFill(0xEEEEEE);
			graphics.drawRect(0, 0, SIZE, SIZE);
			graphics.endFill();
			
			_initSound();
		}
		
		//音の準備
		private function _initSound():void {
            _snd = new Sound();
            _snd.addEventListener(Event.COMPLETE, function(e:Event):void {
				_snd.removeEventListener(Event.COMPLETE, arguments.callee);
				_sndCh = _snd.play(0, 5);
				addEventListener(Event.ENTER_FRAME, _onEnterFrame);
				_initQBox2D(true, _leftBallArr, _leftBoxArr);//left
				_initQBox2D(false, _rightBallArr, _rightBoxArr);//right
			}, false, 0, true);
            _snd.load(new URLRequest(PATH), new SoundLoaderContext(10, true));
            _ba = new ByteArray();
        }
		
		//QuickBox2Dの準備する	
		private function _initQBox2D(lr:Boolean, ballArr:Array, boxArr:Array) :void {	//(lr true:left ,false:right)
			var mc:MovieClip = new MovieClip();
			var sp:Sprite = new Sprite();
			sp.graphics.beginFill(0x0);
			var lt:Number = lr ? 0 : SIZE / 2;
			sp.graphics.drawRect(lt, 0, SIZE/2, SIZE);
			sp.graphics.endFill();
			mc.mask = sp
			addChild(mc);
			var g:Number = lr ? 9.8 : -9.8;
			var sim:QuickBox2D = new QuickBox2D(mc, { gravityX:g, gravityY:0 } );
			
			//ballを作る
			var xx:Number = lr ? 0 : QBSIZE;
			for (var j:int = 0; j < BALL; j++ ) ballArr[j]  = sim.addCircle( { x:xx , y:Math.random() * QBSIZE, radius:1.3, density:5, restitution:0.5, lineAlpha:1, lineColor:0x3370FF, lineThickness:20, fillColor:0xFFFFFF } ) as QuickObject;
			
			//boxを作る
			for (var i:int = 0; i < 8; i++) boxArr[i]  = sim.addBox( { x:0, y:i * 2.21, width:16, height:2, angle:0, density:0, fillColor:0xFFFFFF, lineAlpha:0 } )as QuickObject;
			
			var con:QuickContacts = sim.addContactListener();
			con.addEventListener(QuickContacts.ADD, function(e:Event):void {
				for (var k:int = 0; k < BALL; k++) {
					var ball:QuickObject = ballArr[k];
					if (con.inCurrentContact(ball)) {
						//trace("x" + con.currentPoint.position.x + "    y" + con.currentPoint.position.y + "    v" + con.currentPoint.velocity.LengthSquared());
						var v:Number = con.currentPoint.velocity.LengthSquared();
						if (v > 3)	addChild(new PlusEffect(con.currentPoint.position.x*30, con.currentPoint.position.y*30, v / 100));
					}
				}
			});
			sim.start();
		}
		
		//毎フレームの処理
		private function _onEnterFrame(e:Event):void {
			SoundMixer.computeSpectrum(_ba, true, 32);
			//音源を解析
			for (var side:int = 0; side < 2; side++) {
				for (var i:int = 0; i < CH; i++) {
					var p:Number = _ba.readFloat();
					if (i % 32 == 0) {
						if (side==0){_leftBoxArr[(i/32)>>0].x = -p*5+8+QBSIZE/2;}
						else {_rightBoxArr[(i/32)>>0].x = p*5-8+QBSIZE/2;}
					}
				}
			}
			// ボールが領域から出たら
			for (i = 0; i < BALL; i++) {
				_leftBallArr[i].y = _calcY( _leftBallArr[i].y, 1.3, QBSIZE); 
				if (_leftBallArr[i].x > QBSIZE / 2) _leftBallArr[i].x = 0;
				_rightBallArr[i].y = _calcY( _rightBallArr[i].y, 1.3, QBSIZE); 
				if (_rightBallArr[i].x < QBSIZE / 2) _rightBallArr[i].x = QBSIZE;
			}
		}
		
		private function _calcY(y:Number, r:Number, w:Number):Number {
			if (y < -r) return r+w;
			if (y > r + w) return -r;
			return y;
		}
	}
}

import flash.display.Graphics;
import flash.display.Sprite;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.events.TweenEvent;
import org.libspark.betweenas3.tweens.ITween;

class PlusEffect extends Sprite {
	private const W:Number = 30;
	private const H:Number = 90;
	
	public function PlusEffect(xx:Number, yy:Number , scale:Number = 1) {
		this.x = xx;
		this.y = yy;
		var hh:Number = H * scale, g:Graphics = this.graphics;
		g.lineStyle(W * scale, 0xFFFF33, 1, false, "normal",	"none");
		graphics.drawPath(Vector.<int>([1, 2, 1, 2]), Vector.<Number>([0, -hh / 2, 0, hh / 2, -hh / 2 , 0, hh / 2 , 0]));
		var it:ITween = BetweenAS3.tween( this, {scaleX:0.5, scaleY:0.5, alpha:0}, null, 1);
		it.addEventListener(TweenEvent.COMPLETE, _complete );
		it.play();
	}
	
	private function _abs(num:Number):Number {
		return (num ^ (num >> 31)) - (num >> 31)
	}
	
	private function _complete(e:TweenEvent):void {
		this.parent.removeChild( this );
	}
}