イシカワタケループ -soundSpectrumCity-
zonnbeさんの
http://wonderfl.net/c/o6k7
をビジュアライザとして流用。
APIがそのまま音ソースの場所に変換されるのでセキュリティの回避でとりあえずURLLoader.loadを先に叩いてるんだけど、スマートな方法ないっすかね。サーバ固定ならポリシーファイルチェック最初に一回走らせればいいんだけども。
-- forked from
soundcloud.comの特定のアーティスト曲をループ再生します。
サンプルとしてイシカワタケル氏を使わせてもらいました。
http://soundcloud.com/takerui
つぶやきボタン付き。
package
{
import com.bit101.components.PushButton;
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.media.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
import flash.ui.*;
import flash.utils.*;
import frocessing.color.ColorHSV;
[SWF(width=465,height=465,backgroundColor=0x000000,frameRate=30)]
public class ASTest extends Sprite
{
/**
* soundcloudのアプリ申請するともらえるクライアントID
* みんなも早速登録しよう
* http://soundcloud.com
*/
private const APP_ID:String = '889391312091fc00a7e03245c4ce7b8e';
/**
* 取得したい作曲者のsoundcloud上のID。ユーザのページのURLと同じ。
* サンプルとしてtakerui氏を使わせてもらいました
* http://soundcloud.com/takerui
*/
private const ARTIST_ID:String = 'takerui';
private var _listGetCommand:ListGetCommand;
private var _index:int = 0;
private var _nextButton:PushButton;
private var _prevButton:PushButton;
private var _toggleButton:PushButton;
private var _linkButton:PushButton;
private var _tweetButton:PushButton;
private var _infoTF:TextField;
private var _sound:Sound;
private var _channel:SoundChannel;
private var _lastPosition:Number;
private var _urlloader:URLLoader;
private var SECTOR:int = 10;
private var LEVEL:int = 3;
private var LEVEL_HEIGHT:int = 20;
private var RADIUSX:int = 30;
private var RADIUSZ:int = 15;
private var edgeA:Array = new Array();
private var edgeB:Array = new Array();
private var D2R:Number = Math.PI/180;
private var R2D:Number = 180/Math.PI;
private var cPos:Dot = new Dot(0, 0);
private var points:Array = new Array();
//planning
private var regions:Array = new Array();
private var gCount:int = 300;
private var gwidth:int = 1000;//stage.stageWidth;
private var gheight:int = 1000;//stage.stageHeight;
//building
private var blength:Number = 100;
private var bwidth:Number = 200;
private var bheight:Number = 200;
private var offset:Dot = new Dot(-gwidth/2, -gheight/2);
private var autoAlign:Boolean = false;
//////////////////////////////////////////////////////////////////////////////////////////////////
// drawTriangles
//////////////////////////////////////////////////////////////////////////////////////////////////
private var viewport:Shape = new Shape();
private var world:Matrix3D = new Matrix3D();
private var vertices:Vector.<Number> = new Vector.<Number>(0, false);
private var projected:Vector.<Number> = new Vector.<Number>(0, false);
private var indices:Vector.<int> = new Vector.<int>(0, false);
private var uvtData:Vector.<Number> = new Vector.<Number>(0, false);
private var projection:PerspectiveProjection = new PerspectiveProjection();
private var sortedIndices:Vector.<int>;
private var faces:Array = [];
/**/
/////////////////////////////////////////////////////////////////////////////////////////////////
private var sort_count:int = 0;
private var rotate:Number = 0;
private var refrest_sort_at:int = 100;
/////////////////////////////////////////////////////////////////////////////////////////////////
//private var snd:Sound;
private var bytes:ByteArray = new ByteArray();
private var bitmapData:BitmapData = new BitmapData(500,500, false, 0xFFFFFFFF);
private var colors:Array = [0xFFCC32,0x333333,0x333333];
private var alphas:Array = [1,0,0];
private var ratios:Array = [0,64,255];
private var m:Matrix = new Matrix();
private var light:Sprite = new Sprite();
private var lightRatio:Number = 48;
private var ct:ColorTransform = new ColorTransform(1,1,1,0.8);
private var transparent:Boolean = false;
////////////////////////////////////////////////////////////////////////////////////////////////
private var landVertices:Vector.<Number> = new Vector.<Number>(0, false);
private var landProjected:Vector.<Number> = new Vector.<Number>(0, false);
private var landIndices:Vector.<int> = new Vector.<int>(0, false);
private var landUvtData:Vector.<Number> = new Vector.<Number>(0, false);
////////////////////////////////////////////////////////////////////////////////////////////////
private var traffic:Array = new Array();
private var landResizing:Number = 0.3;
private var land_bmpd:BitmapData = new BitmapData(gwidth*landResizing, gheight*landResizing,false,0x0);
private var top_down_view:Boolean = false;
private var white_buildings:Boolean = false;
///////////////////////////////////////////////////////////////////
private var windowX:int = 32;
private var windowY:int = 16;
private var trafficTimer:Timer;
private var timerSpeed:int = 3;
private var timerCount:int = 0;
//private var trafficSpeedLabel:TextField = new TextField();
private var buildingsTxt:String = "";
private var tf:TextFormat = new TextFormat();
private var vcolor:ColorHSV = new ColorHSV(0);
private var varyColor:int = 0;
private var staticColor:uint = 0xFFFFCC32;
// dynamic link to url
/////////////////////////////////////////////////////////////////////
private var url:String = "http://level0.kayac.com/images/murai/Digi_GAlessio_-_08_-_ekiti_son_feat_valeska_-_april_deegee_rmx.mp3";
//private var inputText:InputText;
//private var playButton:PushButton;
//private var soundChannel:SoundChannel = new SoundChannel();
[SWF(width=465,height=465,backgroundColor=0x000011,frameRate=60)]
public function ASTest()
{
addEventListener(Event.ADDED_TO_STAGE, init);
//init();
}
private function init(evt:Event = null):void
{
initCity();
constructUI();
constructLogic();
go();
}
private function constructUI():void
{
_nextButton = new PushButton();
_prevButton = new PushButton();
_toggleButton = new PushButton();
_linkButton = new PushButton();
_tweetButton = new PushButton();
_infoTF = new TextField();
_nextButton.label = 'next ->';
_prevButton.label = '<- prev';
_toggleButton.label = 'pause';
_linkButton.label = 'permalink';
_tweetButton.label = 'tweet';
_toggleButton.x = 110;
_nextButton.x = _tweetButton.x = 220;
_linkButton.y = _tweetButton.y = 30;
addChild(_nextButton);
addChild(_prevButton);
addChild(_toggleButton);
addChild(_linkButton);
addChild(_tweetButton);
_nextButton.addEventListener(MouseEvent.CLICK, onClick);
_prevButton.addEventListener(MouseEvent.CLICK, onClick);
_toggleButton.addEventListener(MouseEvent.CLICK, onClick);
_linkButton.addEventListener(MouseEvent.CLICK, onClick);
_tweetButton.addEventListener(MouseEvent.CLICK, onClick);
_infoTF = new TextField();
_infoTF.autoSize = TextFieldAutoSize.LEFT;
_infoTF.textColor = 0xffffff;
_infoTF.y = 150;
addChild(_infoTF);
}
private function constructLogic():void
{
_listGetCommand = new ListGetCommand(APP_ID, ARTIST_ID);
_listGetCommand.onComplete = playSound;
_urlloader = new URLLoader();
_urlloader.addEventListener(ProgressEvent.PROGRESS, onProgress);
}
private function go():void
{
_infoTF.text = 'Loading...';
_listGetCommand.execute();
}
private function playSound():void
{
if(Values.vector.length == 0)
{
_infoTF.text = 'oops something is technically wrong';
return;
}
if(_index >= Values.vector.length)
{
_index = 0;
playSound();
return;
}
if(_index < 0)
{
_index = Values.vector.length-1;
playSound();
return;
}
if(_channel != null)
{
_channel.stop();
_channel.removeEventListener(Event.SOUND_COMPLETE, onSoundComp);
}
var song:SongModel = Values.vector[_index];
var req:URLRequest = new URLRequest(song.stream_url + '?client_id=' + APP_ID);
_urlloader.load(req);
_sound = new Sound(req, new SoundLoaderContext(1000, true));
_channel = _sound.play(0,1);
_channel.addEventListener(Event.SOUND_COMPLETE, onSoundComp);
_lastPosition = 0;
_infoTF.text = 'Now Playing: ' + song.title + ' / ' + song.artist;
_toggleButton.label = 'pause';
}
private function pause():void
{
if(_channel!=null)
{
_lastPosition = _channel.position;
_channel.stop();
_toggleButton.label = 'play';
}
}
private function resume():void
{
if(_channel!=null)
{
_channel = _sound.play(_lastPosition, 1);
}
else
{
playSound();
}
_toggleButton.label = 'pause';
}
private function onSoundComp(evt:Event):void
{
_channel.removeEventListener(Event.SOUND_COMPLETE, onSoundComp);
_channel = null;
_index ++;
playSound();
}
private function onClick(evt:MouseEvent):void
{
switch(evt.target)
{
case _nextButton:
_index ++;
playSound();
break;
case _prevButton:
_index --;
playSound();
break;
case _toggleButton:
(_toggleButton.label=='play')?resume():pause();
break;
case _linkButton:
pause();
navigateToURL(new URLRequest(Values.vector[_index].link), '_blank');
break;
case _tweetButton:
navigateToURL(new URLRequest('http://twitter.com/intent/tweet?text=Now Playing: ' + Values.vector[_index].title + ' / ' + Values.vector[_index].artist + '&url=' + Values.vector[_index].link), '_blank');
break;
}
}
private function onProgress(evt:ProgressEvent):void
{
_urlloader.close();
}
private function initCity():void
{
addChild(new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000011)));
addChild(light);
/*
trafficSpeedLabel.text = "traffic speed: 1";
tf.size = 10;
tf.font = "Arial"
trafficSpeedLabel.textColor = 0xFFFFFF;
trafficSpeedLabel.setTextFormat(tf);
trafficSpeedLabel.autoSize = "left";
addChild(trafficSpeedLabel);
trafficSpeedLabel.x = stage.stageWidth - trafficSpeedLabel.width -5;
*/
var mc:MovieClip = new MovieClip();
with(mc.graphics)
{
beginFill(0x0);
drawRect(0,0, stage.stageWidth, 130);
endFill();
}
mc.y = stage.stageHeight - mc.height;
m.translate(stage.stageWidth/2, stage.stageHeight-130);
regions.push(new Region);
regions[0].vertices.push(new Dot(0 ,0));
regions[0].vertices.push(new Dot(gwidth, 0));
regions[0].vertices.push(new Dot(gwidth, gheight));
regions[0].vertices.push(new Dot(0, gheight));
init3D();
}
private function init3D(e:Event = null):void
{
viewport.x = stage.stageWidth / 2;
viewport.y = stage.stageHeight / 2;
addChild(viewport);
projection.fieldOfView = 45;
//add input mp3 url
var panel:Sprite = new Sprite();
/*
inputText = new InputText(panel, stage.stageWidth - 250, 20, "http://level0.kayac.com/images/murai/Digi_GAlessio_-_08_-_ekiti_son_feat_valeska_-_april_deegee_rmx.mp3");
playButton = new PushButton(panel, stage.stageWidth - 45, 20, "play", onClickPlay);
inputText.setSize(200,20);
playButton.setSize(40,20);
*/
addChild(panel);
//planning
generateCity();
constructLand();
/*
snd = new Sound();
snd.load(new URLRequest("http://level0.kayac.com/images/murai/Digi_GAlessio_-_08_-_ekiti_son_feat_valeska_-_april_deegee_rmx.mp3"), new SoundLoaderContext(10,true));
soundChannel = snd.play(0, 9999);
*/
trafficTimer = new Timer(10);
trafficTimer.addEventListener(TimerEvent.TIMER, updateTraffic);
trafficTimer.start();
stage.addEventListener(MouseEvent.MOUSE_DOWN, onmouseDown);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onkeyDown);
stage.addEventListener(Event.ENTER_FRAME, processing);
}
private function onClickPlay(...arg):void
{
/*
soundChannel.stop();
snd = new Sound();
//snd.load(new URLRequest(inputText.text), new SoundLoaderContext(10,true));
soundChannel = snd.play(0, 9999);
*/
}
private function generateCity(m:* = null):void
{
var i:int = 0;
var j:int = 0;
var k:int = 0;
var randomlyPick:int = 0;
var randomlyRatio:Number = 0;
var rFactor:int = 1
var rFrom:int = 2;
var rTo:int = 3;
var limitLength:Number = 10;
var limitSize:Number = 3000;
var align:Boolean = true;
var detectLongest:Boolean = true;
var randomAlign:Boolean = autoAlign;
var aRFactor:int = 1;
while(i<gCount)
{
randomlyPick = int(multipleRandom(rFactor) * regions.length);
randomlyRatio = rFrom+Math.round(multipleRandom(rFactor) * (rTo - rFrom));
if(regions[randomlyPick].pass)
{
if(regions[randomlyPick].needPush2Region(regions, 1/randomlyRatio, limitLength, limitSize, align, detectLongest, randomAlign, aRFactor))
{
regions.splice(randomlyPick,1);
}
}
i++;
}
var tempvertices:Array = new Array();
for(i = 0; i < regions.length; i++)
{
regions[i].getResizedRegionVerticesByRatio(tempvertices, 0.7);
constructBuildingByVertices(tempvertices, m);
tempvertices.splice(0, tempvertices.length);
regions[i].getResizedRegionVerticesByRatio(tempvertices, 0.9);
if(area(tempvertices)>8000)
{
traffic.push(new Array());
for(j = 0; j < tempvertices.length; j++)
{
traffic[traffic.length-1].push(tempvertices[j]);
}
}
tempvertices.splice(0, tempvertices.length);
}
buildingsTxt = "total "+regions.length+" buildings";
updateLabel();
}
private function onmouseDown(e:MouseEvent):void
{
vertices.splice(0, vertices.length);
projected.splice(0, projected.length);
faces.splice(0, faces.length);
indices.splice(0, indices.length);
uvtData.splice(0, uvtData.length);
regions.splice(0, regions.length);
regions.push(new Region);
regions[0].vertices.push(new Dot(0 ,0));
regions[0].vertices.push(new Dot(gwidth, 0));
regions[0].vertices.push(new Dot(gwidth, gheight));
regions[0].vertices.push(new Dot(0, gheight));
traffic.splice(0, traffic.length);
generateCity();
}
private function onkeyDown(e:KeyboardEvent):void
{
switch(e.keyCode)
{
case Keyboard.SPACE:
autoAlign = !autoAlign;
updateLabel();
break;
case Keyboard.SHIFT:
transparent = !transparent;
if(transparent)
bitmapData = new BitmapData(500,500, true, 0xFFFFFFFF);
else
bitmapData = new BitmapData(500,500, false, 0xFFFFFFFF);
break;
case Keyboard.UP:
top_down_view = !top_down_view;
break;
case Keyboard.LEFT:
white_buildings = !white_buildings;
if(white_buildings)
bitmapData = new BitmapData(500,500, true, 0xFFFFFFFF);
else
bitmapData = new BitmapData(500,500, false, 0xFFFFFFFF);
break;
case Keyboard.RIGHT:
if(++timerSpeed==4) timerSpeed = 0;
timerCount = 0;
updateLabel();
break;
case Keyboard.DOWN:
if(++varyColor>4) varyColor = 0;
updateLabel();
break;
}
}
private function processing(e:Event):void
{
update();
render();
}
private function render():void
{
world.identity();
rotate = getTimer() * -0.005;
world.appendRotation(getTimer() * -0.005, Vector3D.Y_AXIS);
if(top_down_view) world.appendRotation(90, Vector3D.X_AXIS);
world.appendTranslation(0, 220, 1000);
world.append(projection.toMatrix3D());
Utils3D.projectVectors(world, vertices, projected, uvtData);
if((rotate-180)/-180>sort_count)
{
resort();
sort_count++;
}
viewport.graphics.clear();
Utils3D.projectVectors(world, landVertices, landProjected, landUvtData);
viewport.graphics.beginBitmapFill(land_bmpd, null, false, false);
viewport.graphics.drawTriangles(landProjected, landIndices, landUvtData, TriangleCulling.NEGATIVE);
viewport.graphics.endFill();
if(white_buildings)
viewport.graphics.beginBitmapFill(new BitmapData(100, 100, true, 0x55FFFFFF), null, false, false);
else
viewport.graphics.beginBitmapFill(bitmapData, null, false, false);
viewport.graphics.drawTriangles(projected, sortedIndices, uvtData, TriangleCulling.NEGATIVE);
viewport.graphics.endFill();
/**/
}
private function resort():void
{
var face:Vector3D;
var inc:int = 0;
var i1:uint = 0x0;
var i2:uint = 0x0;
var i3:uint = 0x0;
var i4:int = 0;
for (var i:int = 0; i<indices.length; i+=3){
i1 = indices[ i+0 ];
i2 = indices[ i+1 ];
i3 = indices[ i+2 ];
face = faces[inc];
face.x = i1;
face.y = i2;
face.z = i3;
face.w = (uvtData[i1 * 3 + 2] + uvtData[i2 * 3 + 2] + uvtData[i3 * 3 + 2]) * 0.333333;
inc++;
}
faces.sortOn("w", Array.NUMERIC);
inc = 0;
for each (face in faces){
sortedIndices[inc++] = face.x;
sortedIndices[inc++] = face.y;
sortedIndices[inc++] = face.z;
}
sort_count = 0;
}
private function update():void
{
SoundMixer.computeSpectrum(bytes, false, 0);
var byteTotal:Number = 0;
var i:int = 0;
var byte:Number = 0;
bytes.position = 0;
var w:int = 20;
var h:int = 25;
bitmapData.colorTransform(bitmapData.rect, ct);
//bitmapData.fillRect(bitmapData.rect, 0x000000);
//bitmapData.applyFilter(bitmapData, bitmapData.rect, new Point(), blurEffect);
var size:Number = bitmapData.width*0.8;
var tcolor:uint = 0;
for(i = 0; i < 512; i++)
{
byte = Math.abs(bytes.readFloat());
byteTotal += byte;
if(byte>0.2)
{
switch(varyColor)
{
case 0:
tcolor = staticColor;
break;
case 1:
vcolor.h = getTimer()/5 + (i)*(360/512);
tcolor = vcolor.value32;
break;
case 2:
vcolor.h = getTimer()/5 + 10.5*i;
tcolor = vcolor.value32;
break;
case 3:
vcolor.h = getTimer()/5 + 100/1000*i;
tcolor = vcolor.value32;
break;
case 4:
vcolor.h = getTimer()/5 + getTimer()*i;
tcolor = vcolor.value32;
break;
}
bitmapData.fillRect(new Rectangle((i%windowX)*(size/windowX),int(i/windowX)*(size/windowY), (size/windowX)-8, (size/windowY)-8), tcolor);
}
}
byteTotal /= 512;
if(300 * byteTotal > lightRatio) lightRatio = 400 * byteTotal;
lightRatio -= (lightRatio-32) * 0.03333333;
ratios[1] = lightRatio;
with(light.graphics)
{
clear();
beginGradientFill(GradientType.RADIAL,colors,alphas,ratios,m);
drawRect(0,0,stage.stageWidth,stage.stageHeight);
endFill();
}
}
private function updateTraffic(e:TimerEvent):void
{
if(++timerCount==timerSpeed)
{
var i:int = 0;
var j:int = 0;
var k:int = 0;
var l:int = 0;
var vx:Number = 0;
var vy:Number = 0;
var vlen:Number = 0;
var tm:Number = 0;
var theRect:Rectangle = new Rectangle();
theRect.width = 2;
theRect.height = 2;
//land_bmpd.fillRect(land_bmpd.rect, 0x0);
land_bmpd.colorTransform(land_bmpd.rect, ct);
for(i = 0; i < traffic.length; i++)
{
for(j = 0; j < traffic[i].length; j++)
{
k = (j+1) % traffic[i].length;
vx = traffic[i][k].x*landResizing - traffic[i][j].x*landResizing;
vy = traffic[i][k].y*landResizing - traffic[i][j].y*landResizing;
vlen = Math.sqrt(vx*vx+vy*vy);
for(l = 0; l < 5; l++)
{
tm = (getTimer()/timerSpeed)%1000 * vlen/1000;
if(tm > vlen/5) tm %= vlen/5;
theRect.x = traffic[i][j].x*landResizing + vx/vlen * (vlen/5 * l + tm);
theRect.y = traffic[i][j].y*landResizing + vy/vlen * (vlen/5 * l + tm);
land_bmpd.fillRect(theRect, 0xFFFF0000);
theRect.x += vx/vlen * vlen/5*0.1;
theRect.y += vy/vlen * vlen/5*0.1;
land_bmpd.fillRect(theRect, 0xFFAA7732);
}
}
}
timerCount = 0;
}
}
private function updateLabel():void
{
/*
var scolor:String = "";
switch(varyColor)
{
case 0:
scolor = "color: Yellow; ";
break;
case 1:
scolor = "color: HSV 1; ";
break;
case 2:
scolor = "color: HSV 2; ";
break;
case 3:
scolor = "color: HSV 3; ";
break;
case 4:
scolor = "color: HSV 4; ";
break;
}
if(autoAlign)
scolor += "align: gridless; ";
else
scolor += "align: by grid; ";
if(timerSpeed == 0)
trafficSpeedLabel.text = scolor + buildingsTxt + "; traffic pause!";
else
trafficSpeedLabel.text = scolor + buildingsTxt + "; traffic speed: "+(4 - timerSpeed);
trafficSpeedLabel.x = stage.stageWidth - trafficSpeedLabel.width;
trafficSpeedLabel.setTextFormat(tf);
*/
}
private function constructBuildingByVertices(va:Array, m:* = null):void
{
var i:int = 0;
var j:int = 0;
var min:Number = bheight*0.20;
var max:Number = bheight*0.80;
var randomlyHeight:Number = min+multipleRandom(2)*max;
var i1:uint = 0;
var i2:uint = 0;
var i3:uint = 0;
var i4:uint = 0;
var indexer:int = 0;
var vratio:Number = 0.8;
for(i = 0; i < va.length; i++)
{
j = (i+1)%va.length;
indexer = vertices.length/3;
vertices.push(va[i].x+offset.x, -randomlyHeight, va[i].y+offset.y); //TL
vertices.push(va[j].x+offset.x, -randomlyHeight, va[j].y+offset.y); //TR
vertices.push(va[i].x+offset.x, 0, va[i].y+offset.y); //BL
vertices.push(va[j].x+offset.x, 0, va[j].y+offset.y); //BR
uvtData.push(0+i*vratio/4, 0, 0); //1
uvtData.push((i+1)*vratio/4, 0, 0); //2
uvtData.push(0+i*vratio/4, vratio, 0); //3
uvtData.push((i+1)*vratio/4, vratio, 0); //4
/**/
i1 = indexer;
i2 = indexer + 1;
i3 = indexer + 2;
i4 = indexer + 3;
indices.push(i1, i2, i3, i3, i2, i4);
faces.push(new Vector3D(), new Vector3D());
}
/**/
indexer = vertices.length/3;
// top
vertices.push(va[1].x+offset.x, -randomlyHeight, va[1].y+offset.y); //TL
vertices.push(va[0].x+offset.x, -randomlyHeight, va[0].y+offset.y); //TR
vertices.push(va[2].x+offset.x, -randomlyHeight, va[2].y+offset.y); //BL
vertices.push(va[3].x+offset.x, -randomlyHeight, va[3].y+offset.y); //BR
if(transparent)
{
uvtData.push(0, 0, 0); //1
uvtData.push(0, 0, 0); //2
uvtData.push(0, 0, 0); //3
uvtData.push(0, 0, 0); //4
} else {
uvtData.push(vratio, vratio, 0); //1
uvtData.push(1, vratio, 0); //2
uvtData.push(vratio, 1, 0); //3
uvtData.push(1, 1, 0); //4
}
i1 = indexer;
i2 = indexer + 1;
i3 = indexer + 2;
i4 = indexer + 3;
indices.push(i1, i2, i3, i3, i2, i4);
faces.push(new Vector3D(), new Vector3D());
/**/
//if(!sortedIndices)
sortedIndices= new Vector.<int>(indices.length, true);
}
private function constructLand():void
{
var i1:uint = 0;
var i2:uint = 1;
var i3:uint = 2;
var i4:uint = 3;
landVertices.push(gwidth-gwidth/2, 0, 0-gheight/2); //TR
landVertices.push(0-gwidth/2, 0, 0-gheight/2); //TL
landVertices.push(gwidth-gwidth/2, 0, gheight-gheight/2); //BL
landVertices.push(0-gwidth/2, 0, gheight-gheight/2); //BR
landUvtData.push(1, 0, 0); //2
landUvtData.push(0, 0, 0); //1
landUvtData.push(1, 1, 0); //4
landUvtData.push(0, 1, 0); //3
landIndices.push(i1, i2, i3, i3, i2, i4);
}
private function multipleRandom(factor:int):Number
{
var counter:int = 0;
var rand:Number = 1;
while(counter++<factor)
{
rand *= Math.random();
}
return rand;
}
private function area(p:Array):Number
{
var i:int = 0;
var j:int = 0;
var a:Number = 0;
i = 0;
while (i < p.length)
{
j = (i + 1) % p.length;
a = a + p[i].x * p[j].y;
a = a - p[i].y * p[j].x;
i++;
}
a = a / 2;
return a;
}
}
}
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.text.*;
import flash.ui.*;
class Region
{
public var vertices:Array = new Array();
public var pass:Boolean = true;
public function Region()
{
}
// right is always equal to edge index, so skip the right function
public function getVerticeAtEdgeLeft(index:int):int
{
return (index+1>3)?0:index+1;
}
public function getOppositeEdgeOfEdge(index:int):int
{
return (index+2>3)?(index+2)%4:index+2;
}
public function needPush2Region(origin:Array, ratio:Number, limitLength:Number = 0.0, limitSize:Number = 0.0, align:Boolean = true, detectLongest:Boolean = true, randomAlign:Boolean = false, aRFactor:int = 1):Boolean
{
var rIndex:int = int(Math.random() * 4);
if(detectLongest)
rIndex = getLongestEdgeStartFromEdge(rIndex);
var rLeft:int = getVerticeAtEdgeLeft(rIndex);
var rRight:int = rIndex;
var vx:Number = vertices[rLeft].x - vertices[rRight].x;
var vy:Number = vertices[rLeft].y - vertices[rRight].y;
var vlen:Number = Math.sqrt(vx*vx+vy*vy);
if(limitLength == 0.0 || vlen>limitLength)
{
var oIndex:int = getOppositeEdgeOfEdge(rIndex);
var oLeft:int = getVerticeAtEdgeLeft(oIndex);
var oRight:int = oIndex;
var rPoint:Dot;
rPoint = getPointAtEdgeByRatio(rIndex, ratio);
var oPoint:Dot;
//oPoint = getPointAtEdgeByPoint(oIndex, rPoint);
if(!randomAlign)
if(align)
oPoint = getPointAtEdgeByRatio(oIndex, 1-ratio);
else
oPoint = getPointAtEdgeByRatio(oIndex, ratio);
else {
if(multipleRandom(aRFactor)<0.5)
{
//oPoint = getPointAtEdgeByRatio(oIndex, 1-ratio);
oPoint = getPointAtEdgeByPoint(oIndex, rPoint);
if(oPoint == null)
{
oPoint = getPointAtEdgeByRatio(oIndex, Math.random()*(1-ratio));
}
} else
oPoint = getPointAtEdgeByRatio(oIndex, ratio);
}/**/
var regionLeft:Region = new Region();
var regionRight:Region = new Region();
regionLeft.vertices.push(vertices[oRight].clone());
regionLeft.vertices.push(oPoint);
regionLeft.vertices.push(rPoint);
regionLeft.vertices.push(vertices[rLeft].clone());
if(limitSize != 0.0 && regionLeft.area()<limitSize)
{
regionLeft.pass = false;
}
origin.push(regionLeft);
regionRight.vertices.push(oPoint);
regionRight.vertices.push(vertices[oLeft].clone());
regionRight.vertices.push(vertices[rRight].clone());
regionRight.vertices.push(rPoint);
if(limitSize != 0.0 && regionRight.area()<limitSize)
{
regionRight.pass = false;
}
origin.push(regionRight);
return true;
}
return false;
}
public function getPointAtEdgeByRatio(index:int, ratio:Number):Dot
{
var jndex:int = (index+1)%4;
var vx:Number = vertices[jndex].x - vertices[index].x;
var vy:Number = vertices[jndex].y - vertices[index].y;
return new Dot(vertices[index].x+vx*ratio, vertices[index].y+vy*ratio);
}
public function getPointAtEdgeByPoint(index:int, p:Dot):Dot
{
var jndex:int = (index+1)%4;
var avx:Number = vertices[jndex].x - vertices[index].x;
var avy:Number = vertices[jndex].y - vertices[index].y;
var vlena:Number = Math.sqrt(avx*avx+avy*avy);
var dist:Number = pdis(vertices[index], vertices[jndex], p);
var bvx:Number = p.x - vertices[index].x;
var bvy:Number = p.y - vertices[index].y;
var vlenb:Number = Math.sqrt(bvx*bvx+bvy*bvy);
var nvlena:Number = Math.sqrt(vlenb*vlenb - dist*dist);
if(nvlena<vlena)
return new Dot(vertices[index].x+nvlena*avx/vlena, vertices[index].y+nvlena*avy/vlena);
return null;
}
public function getLengthOfEdge(index:int):Number
{
var nextIndex:int = (index+1)%4;
var vx:Number = vertices[nextIndex].x - vertices[index].x;
var vy:Number = vertices[nextIndex].y - vertices[index].y;
return Math.sqrt(vx*vx+vy*vy);
}
public function getLongestEdgeStartFromEdge(index:int):int
{
var li:int = index;
var ci:int = index;
var startIndex:int = index;
var longestLength:Number = getLengthOfEdge(index);
var currLength:Number = 0;
do{
ci = (ci+1)%4;
currLength = getLengthOfEdge(ci);
if(currLength>longestLength)
{
longestLength = currLength;
li = ci;
}
} while(ci != startIndex);
return li;
}
public function area():Number
{
var i:int = 0;
var j:int = 0;
var a:Number = 0;
i = 0;
while (i < vertices.length)
{
j = (i + 1) % vertices.length;
a = a + vertices[i].x * vertices[j].y;
a = a - vertices[i].y * vertices[j].x;
i++;
}
a = a / 2;
return a;
}
public function multipleRandom(factor:int):Number
{
var counter:int = 0;
var rand:Number = 1;
while(counter++<factor)
{
rand *= Math.random();
}
return rand;
}
public function pdis(a:Dot, b:Dot, c:Dot):Number
{
var t:Dot = new Dot(b.x-a.x, b.y-a.y);// # Vector ab
var dd:Number = Math.sqrt(t.x*t.x+t.y*t.y);// # Length of ab
t.val_p_(t.x/dd, t.y/dd);// # unit vector of ab
var n:Dot = new Dot(-t.y, t.x);// # normal unit vector to ab
var ac:Dot = new Dot(c.x-a.x, c.y-a.y);// # vector ac
return Math.abs(ac.x*n.x+ac.y*n.y);
}
public function com() : Dot// centre of mass
{
var cm:Dot = new Dot(0, 0);
var tx:Number = 0;
var ty:Number = 0;
var a:Number = area();
var i:int = 0;
var j:int = 0;
var d:Number = 0;
i = 0;
while (i < vertices.length)
{
j = (i + 1) % vertices.length;
d = vertices[i].x * vertices[j].y - vertices[j].x * vertices[i].y;
tx = tx + (vertices[i].x + vertices[j].x) * d;
ty = ty + (vertices[i].y + vertices[j].y) * d;
i++;
}
a = a * 6;
d = 1 / a;
tx = tx * d;
ty = ty * d;
cm.x = tx;
cm.y = ty;
return cm;
}
public function getResizedRegionVerticesByRatio(target:Array, ratio:Number = 1.0):void
{
var centerOfMass:Dot = com();
var vx:Number = 0;
var vy:Number = 0;
var i:int = 0;
for(i = 0; i < vertices.length; i++)
{
vx = vertices[i].x - centerOfMass.x;
vy = vertices[i].y - centerOfMass.y;
target.push(new Dot(centerOfMass.x+vx*ratio, centerOfMass.y+vy*ratio));
}
}
}
class Dot
{
public var x:Number = 0;
public var y:Number = 0;
public var tx:Number = 0;
public var ty:Number = 0;
public var vx:Number = 0;
public var vy:Number = 0;
public var angle:Number = 0;
public var size:Number = 0;
public var speed:Number = 0;
public var m:Number = 0;
public var rad:Number = 0;
public function Dot(px:Number,py:Number)
{
x = px;
y = py;
tx = x;
ty = y;
}
public function clone():Dot
{
return new Dot(this.x, this.y);
}
public function val_(p:Dot):Dot
{
x = p.x;
y = p.y;
return this;
}
public function val_p_(px:Number, py:Number):Dot
{
x = px;
y = py;
return this;
}
public function add_(px:Number, py:Number):Dot
{
x += px;
y += py;
return this;
}
}
import com.adobe.serialization.json.JSON;
import flash.net.URLRequest;
import jp.progression.casts.*;
import jp.progression.commands.*;
import jp.progression.commands.display.*;
import jp.progression.commands.lists.*;
import jp.progression.commands.managers.*;
import jp.progression.commands.media.*;
import jp.progression.commands.net.*;
import jp.progression.commands.tweens.*;
import jp.progression.data.*;
import jp.progression.events.*;
import jp.progression.scenes.*;
class ListGetCommand extends SerialList
{
private var _app_id:String;
private var _artist_id:String;
public function ListGetCommand ( app_id:String = '889391312091fc00a7e03245c4ce7b8e', artist_id:String = 'takerui', initObject:Object = null ) {
// 親クラスを初期化します。
super( initObject );
_app_id = app_id;
_artist_id = artist_id;
// 実行したいコマンド群を登録します。
addCommand(
new LoadURL(new URLRequest('http://api.soundcloud.com/users/' + _artist_id + '/tracks.json?client_id=' + _app_id), {catchError:function():void{
Values.json = null;
executeComplete();
}}
)
,new Func(function():void{
var res:String = this.latestData;
var json:Object;
try
{
json = JSON.decode(res);
}
catch(error:Error)
{
}
Values.json = json;
Values.vector = new Vector.<SongModel>();
for each(var item:Object in json)
{
var song:SongModel = new SongModel(item.title, item.user.username, item.permalink_url, item.stream_url);
(song.stream_url != null)?Values.vector.push(song):0;
}
})
);
}
/**
* インスタンスのコピーを作成して、各プロパティの値を元のプロパティの値と一致するように設定します。
*/
override public function clone():Command {
return new ListGetCommand( _app_id, _artist_id, this );
}
}
class SongModel
{
public var title:String;
public var artist:String;
public var link:String;
public var stream_url:String;
//ほかにもいろいろプロパティとれる
public function SongModel(title:String, artist:String, link:String, stream_url:String)
{
this.title = title;
this.artist = artist;
this.link = link;
this.stream_url = stream_url;
}
}
class Values
{
public static var json:Object;
public static var vector:Vector.<SongModel>;
}