forked from: forked from: まだ研究中 シーッ!
Draw a Tasty Ramen !
*
* You can edit and modify every piece of this code.
* Load more pictures of GU (ingredients of ramen)
* from flickr or draw one by yourself.
* Make it look tasty.
*
♥0 |
Line 293 |
Modified 2010-02-01 06:19:50 |
MIT License
archived:2017-03-20 14:24:58
ActionScript3 source code
/**
* Copyright Limeflash ( http://wonderfl.net/user/Limeflash )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/fhDD
*/
// forked from hacker_57o638hu's forked from: まだ研究中 シーッ!
// forked from alumican_net's まだ研究中 シーッ!
/*
*
* Draw a Tasty Ramen !
*
* You can edit and modify every piece of this code.
* Load more pictures of GU (ingredients of ramen)
* from flickr or draw one by yourself.
* Make it look tasty.
*
*/
package
{
import flash.display.*;
import org.libspark.thread.*;
import com.flashdynamix.utils.SWFProfiler;
public class FlashTest extends Sprite
{
public function FlashTest():void
{
//ステージ初期化
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.frameRate = 60;
//スレッドの開始
Thread.initialize(new EnterFrameThreadExecutor());
new MainThread(this).start();
//プロファイラの表示
SWFProfiler.init(this);
}
}
}
import flash.display.*;
import flash.errors.IOError;
import flash.events.*;
import flash.geom.Matrix;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.*;
import flash.system.LoaderContext;
import flash.text.*;
import flash.utils.ByteArray;
import org.libspark.thread.*;
import org.libspark.thread.errors.*;
import org.libspark.thread.threads.display.LoaderThread;
import org.libspark.thread.threads.media.SoundLoaderThread;
import org.libspark.thread.threads.net.URLLoaderThread;
import org.libspark.thread.utils.*;
internal class MainThread extends Thread
{
//----------------------------------------
//CONSTANTS
//----------------------------------------
/**
* ピッチ可変再生のためのバッファ長
*/
private const SOUND_BUFFER_LENGHT:uint = 2048;
/**
* Soundファイルのビットレート(KHz)
*/
private const SOUND_BITRATE:Number = 44.1;
/**
* π
*/
private const PI:Number = Math.PI;
private const PI2:Number = Math.PI * 2;
/**
* ステージサイズ
*/
private const W:uint = 465;
private const H:uint = 465;
//----------------------------------------
//VARIABLES
//----------------------------------------
//ベースSprite
private var _base:Sprite;
//外部Bitmap配列
private var _bmps:Array;
//外部Sound配列
private var _sounds:Array;
//合成Sound
private var _track:Sound;
//Soundの再生ピッチ
private var _soundPitch:Number;
//Soundの生データ
private var _soundBytes:ByteArray;
//Soundの再生位置
private var _soundPosition:Number;
//Soundの総バイト数
private var _soundBytesTotal:Number;
//動的音生成用のSound
private var _soundDynamic:Sound;
//動的音生成用のSoundChannel
private var _soundChannel:SoundChannel;
//ディスク用Sprite
private var _disc:Sprite;
//どんぶり
private var _bowl:Sprite;
//ディスクをスクラッチ中ならtrue
private var _isScratching:Boolean;
//スクラッチ速度
private var _scratchVelocity:Number;
//スクラッチの角度
private var _newScratchAngle:Number;
private var _oldScratchAngle:Number;
//SEの画像データ
private var _notes:Array;
//SEの音データ
private var _noteBytes:Array;
//stageの参照
public var stage:Stage;
//デバッグ用TextField
public var field:TextField;
//----------------------------------------
//METHODS
//----------------------------------------
public function MainThread(base:Sprite):void
{
this.stage = base.stage;
_base = base;
//デバッグ用TextFieldの生成
field = _base.addChild(new TextField()) as TextField;
field.width = 465;
field.height = 465;
field.text = "test";
field.selectable = false;
field.mouseEnabled = false;
}
/**
* スレッドの実行関数
*/
override protected function run():void
{
_loadImages();
}
/**
* 画像の読み込みを開始する
*/
private function _loadImages():void
{
var urls:Array = [
"http://lab.alumican.net/wonderfl/ramen_beats_box/3787648401_0b3d62a314_o.png", /* ラーメン */
"http://lab.alumican.net/wonderfl/ramen_beats_box/3787648415_1f857d46cf_o.png", /* ナルト1 */
"http://lab.alumican.net/wonderfl/ramen_beats_box/3788456920_5101174e6c_o.png", /* ナルト2 */
"http://lab.alumican.net/wonderfl/ramen_beats_box/3788456906_91e357245f_o.png" /* メンマ */
];
_loadDatas(urls, "img", _onImagesLoadComplete);
}
/**
* 画像の読み込み完了ハンドラ
*/
private function _onImagesLoadComplete(container:Array, type:String):void
{
//読み込んだBitmap配列
_bmps = container;
//----------------------------------------
//ラーメンの配置
_disc = _base.addChild( new Sprite() ) as Sprite;
_disc.x = W / 2;
_disc.y = H / 2 - 30;
_disc.scaleX = _disc.scaleY = 0.7;
var bowlBmp:Bitmap = _bmps[0];
bowlBmp.smoothing = true;
bowlBmp.x = -bowlBmp.width / 2;
bowlBmp.y = -bowlBmp.height / 2;
_bowl = new Sprite();
_bowl.addChild(bowlBmp);
_disc.addChild(_bowl);
//----------------------------------------
//具材
_notes = new Array(_bmps.length - 1);
var offsetX:Number = (W - 80 * (_notes.length - 1)) / 2;
for (var i:int = 0; i < _notes.length; ++i)
{
var bmp:Bitmap = _bmps[i + 1];
var scale:Number = 60 / bmp.width;
var resized:BitmapData = new BitmapData(scale * bmp.width, scale * bmp.height, true, 0x0);
resized.draw(bmp.bitmapData, new Matrix(scale, 0, 0, scale));
var bmp2:Bitmap = new Bitmap(resized);
bmp2.x = -bmp2.width / 2;
bmp2.y = -bmp2.height / 2;
var spr:Sprite = new Sprite();
spr.addChild(bmp2);
spr.x = offsetX + i * 80;
spr.y = H - 40;
_base.addChild(spr);
_notes[i] = spr;
}
//----------------------------------------
//音の読み込みを開始する
_loadSounds();
}
/**
* 音の読み込みを開始する
*/
private function _loadSounds():void
{
var urls:Array = [
//"http://lab.alumican.net/wonderfl/ramen_beats_box/p-stone.mp3", /* ベーストラック */
"http://lab.alumican.net/wonderfl/ramen_beats_box/bit243-1.mp3", /* ベーストラック */
"http://lab.alumican.net/wonderfl/ramen_beats_box/hat_close_003.mp3",
"http://lab.alumican.net/wonderfl/ramen_beats_box/kick_002.mp3",
"http://lab.alumican.net/wonderfl/ramen_beats_box/snare_002.mp3"
];
_loadDatas(urls, "sound", _onSoundsLoadComplete);
}
/**
* 音の読み込み完了ハンドラ
*/
private function _onSoundsLoadComplete(container:Array, type:String):void
{
//読み込んだSound配列
_sounds = container;
//リズムトラック
_track = _sounds[0];
//SEオブジェクト
_noteBytes = new Array(_sounds.length - 1);
for (var i:int = 0; i < _noteBytes.length; ++i)
{
//Soundオブジェクトから生データ(ByteArray)を抽出する
var se:Sound = _sounds[i + 1];
var ba:ByteArray = new ByteArray();
se.extract(ba, se.length * SOUND_BITRATE * 8);
_noteBytes[i] = ba;
}
//再生開始
play();
}
/**
* Music start!!
*/
private function play():void
{
//再生開始
_soundPitch = 1;
_startSound(_track);
//ディスクの回転開始
_disc.rotation = 0;
//ピッチ計測開始
_soundPitch = 1;
_isScratching = false;
_bowl.addEventListener(Event.ENTER_FRAME, _updatePitch);
_bowl.addEventListener(MouseEvent.MOUSE_DOWN, _mouseDownHandler);
_bowl.buttonMode = true;
_newScratchAngle= Math.atan2(_base.mouseY - _disc.y, _base.mouseX - _disc.x);
_oldScratchAngle = _newScratchAngle;
_scratchVelocity = 0;
}
/**
* ピッチ調整
*/
private function _updatePitch(e:Event):void
{
_oldScratchAngle = _newScratchAngle;
_newScratchAngle = Math.atan2(_base.mouseY - _disc.y, _base.mouseX - _disc.x);
var targetPitch:Number;
if (_isScratching)
{
var targetVelocity:Number = _newScratchAngle - _oldScratchAngle;
if (targetVelocity < 0 ) targetVelocity += PI2;
if (targetVelocity > PI) targetVelocity -= PI2;
targetVelocity *= 50;
_scratchVelocity += (targetVelocity - _scratchVelocity) * 0.5;
targetPitch = _scratchVelocity;
}
else
{
_scratchVelocity += (0 - _scratchVelocity) * 0.1;
targetPitch = 1.0 + _scratchVelocity;
}
_soundPitch += (targetPitch - _soundPitch) * 0.1;
}
/**
* マウスダウンハンドラ
*/
private function _mouseDownHandler(e:MouseEvent):void
{
_isScratching = true;
stage.addEventListener(MouseEvent.MOUSE_UP, _mouseUpHandler);
}
/**
* マウスアップハンドラ
*/
private function _mouseUpHandler(e:MouseEvent):void
{
_isScratching = false;
stage.removeEventListener(MouseEvent.MOUSE_UP, _mouseUpHandler);
}
/**
* サウンドの再生を開始する
*/
private function _startSound(sound:Sound):void
{
_soundBytes = new ByteArray();
//Soundオブジェクトから生データ(ByteArray)を抽出する
while (sound.extract(_soundBytes, SOUND_BUFFER_LENGHT) >= SOUND_BUFFER_LENGHT) { };
//Sound再生ヘッダを先頭へ移動する
_soundPosition = 0;
//Soundのバイト数を取得する
_soundBytesTotal = _soundBytes.length;
//3倍にする(読み取り領域がはみ出たときのため)
_soundBytes.writeBytes(_soundBytes);
_soundBytes.writeBytes(_soundBytes);
//空のSoundを再生開始する
_soundDynamic = new Sound();
_soundDynamic.addEventListener(SampleDataEvent.SAMPLE_DATA, _onSoundSampleDataHandler);
_soundChannel = _soundDynamic.play();
_synthSound(_noteBytes[2], 0);
}
/**
* サウンドのサンプルデータハンドラ
*/
private function _onSoundSampleDataHandler(e:SampleDataEvent):void
{
//ピッチを0.5の倍数に調整する
var pitch:Number = Math.round(_soundPitch * 2) / 2;
for (var i:uint = 0; i < SOUND_BUFFER_LENGHT; ++i)
{
//ByteArrayの読み取りヘッダを移動する
_soundPosition += pitch * 8;
//ループ処理
if (_soundPosition >= _soundBytesTotal - 8) _soundPosition -= _soundBytesTotal;
if (_soundPosition < 8 ) _soundPosition += _soundBytesTotal;
//読み込みヘッダの移動(1トラック分オフセット)
_soundBytes.position = _soundBytesTotal + _soundPosition;
//ByteArrayの読み込みと書き込み
e.data.writeFloat( _soundBytes.readFloat() );
e.data.writeFloat( _soundBytes.readFloat() );
}
_disc.rotation = 360 * _soundPosition / _soundBytesTotal;
}
/**
* Soundを合成する
*/
private function _synthSound(bytes:ByteArray, position:uint):void
{
var offset0:int = -_soundBytesTotal;
var offset1:int = +_soundBytesTotal;
var len:uint = bytes.length;
var last:uint = position + len;
var dst:Number;
var src:Number;
bytes.position = 0;
for (var i:uint = position; i < last; i += 4)
{
//合成
_soundBytes.position = i;
src = _soundBytes.readFloat();
dst = _soundBytes.readFloat() + bytes.readFloat();
dst *= 0.9;
//中心の波形に書き込む
_soundBytes.position = i;
_soundBytes.writeFloat(dst);
//前の波形に書き込む
_soundBytes.position = i + offset0;
_soundBytes.writeFloat(dst);
//後ろの波形に書き込む
if (i + len < _soundBytesTotal)
{
_soundBytes.position = i + offset1;
_soundBytes.writeFloat(dst);
}
}
}
//----------------------------------------
//VERSATILE METHODS
//----------------------------------------
/**
* URL配列で与えられたデータを読み込む汎用メソッド
*/
private function _loadDatas(urls:Array, type:String, onComplete:Function = null, onError:Function = null):void
{
//読み込んだデータを格納する配列
var container:Array = new Array();
//読み込み開始
var loaders:ParallelExecutor = new ParallelExecutor();
for (var i:uint = 0; i < urls.length; ++i)
{
var thread:Thread = (type == "text" ) ? new URLLoaderThread( new URLRequest(urls[i]) ) :
(type == "sound") ? new SoundLoaderThread( new URLRequest(urls[i]) ) :
new LoaderThread( new URLRequest(urls[i]), new LoaderContext(true) ) ;
loaders.addThread(thread);
}
loaders.start();
loaders.join();
//読み込み完了ハンドラ
function onLoadComplete():void
{
//読み込んだデータを配列に格納する
for (var i:uint = 0; i < urls.length; ++i)
{
var data:* = (type == "text" ) ? URLLoaderThread( loaders.getThreadAt(i) ).loader.data :
(type == "sound") ? SoundLoaderThread( loaders.getThreadAt(i) ).sound :
LoaderThread( loaders.getThreadAt(i) ).loader.content ;
container.push(data);
}
//コールバック関数の呼び出し
if (onComplete != null) onComplete(container, type);
}
//読み込みエラーハンドラ
function onLoadError(e:Error, t:Thread):void
{
var url:String = (type == "text" ) ? URLLoaderThread(t).request.url :
(type == "sound") ? SoundLoaderThread(t).request.url :
LoaderThread(t).request.url ;
trace("error : _loadDatas, url = " + url + ", type = " + type);
//コールバック関数の呼び出し
(onError != null) ? onError() : next(null);
}
//ハンドラの登録
next(onLoadComplete);
error(IOError, onLoadComplete);
error(SecurityError, onLoadError);
}
/**
* デバッグ出力
*/
public function log(...args):void
{
var argn:uint = args.length;
for (var i:uint = 0; i < argn; ++i)
{
if (args[i] == "")
{
field.text = "";
continue;
}
field.appendText(String(args[i]) + "\n");
}
}
}