音波形に対応したサウンドボタン
※soundボタンをクリックすると音が鳴るので注意。
サウンドスペクトラムを使って、音にシンクロしたサウンドボタン用のクラスを作ってみた。最初にsetPixel()でピクセルを描画しておいて、スペクトラム波形に合わせてscaleYを変化させてます。下記がそのクラスファイル。
SoundSpectrum.as
{
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.media.SoundMixer;
import flash.utils.ByteArray;
public class SoundSpectrum extends Sprite
{
private var lineNum:uint;
private var lineHeight:uint;
private var lineInterval:uint;
private var bmAry:Array = [];
//------------------------------
// コンストラクタ
//------------------------------
public function SoundSpectrum(targetNum:uint = 5, targetHeight:uint = 20, targetInterval:uint = 1, targetColor:uint = 0x000000)
{
lineNum = targetNum;
lineHeight = targetHeight;
lineInterval = targetInterval;
this.addEventListener(Event.ENTER_FRAME, onRender);
//-----[ピクセルの描画]
var bmd:BitmapData;
var bm:Bitmap;
for (var i = 0; i <lineNum; i++)
{
bmd = new BitmapData(1, 100);
bm = new Bitmap(bmd);
this.addChild(bm);
bm.x = i * (lineInterval + 1);
bmd.setPixel(0, 0, targetColor);
bmAry.push(bm);
}
bmd.dispose();
}
//------------------------------
// レンダー
//------------------------------
private function onRender(e:Event):void
{
var count:uint = 256 / lineNum;
var value:Number;
var ba:ByteArray = new ByteArray();
SoundMixer.computeSpectrum(ba, false, 0);
for (var i:uint = 0; i <256; i++)
{
value = -ba.readFloat() * lineHeight - 1;
for (var j:uint = 0; j <lineNum; j++)
{
if (i == Math.floor(count * j)) bmAry[j].scaleY = value;
}
}
}
}
}
続いてドキュメントクラスには以下のように記述します。引数はSoundSpectrum(ラインを何本にするか, ラインの最大高さ, ラインの間隔, ラインの色)となります。インスタンス化した後にx,yプロパティを与えてaddChild()でステージに配置。デフォルトで数値を持たしているので、カスタマイズしたくない場合は引数なしでも大丈夫です。
soundBtn.addChild(sp);
sp.x = 32;
sp.y = 10;
PHPに複数データを渡してみる
AS3ではURLRequest.dataで送信できるデータは1つなので、複数の変数をPHPに渡したい場合はURLVariablesを使う。URLVariablesをインスタンス化した後に、通常のオブジェクトと同様、任意のプロパティに値を格納していく。ここでは「title」、「url」、「text」の3つの要素を各プロパティに入れている。URLVariablesに格納した後は、URLRequestにて呼び出したいPHPのパスと通信方法を指定(今回はPOST通信)し、URLRequest.dataにURLVariablesを突っ込む。最後にnavigateToURL()でPHPを表示させ、Flashからデータを受け取っているか確認する。
Main.as
{
import flash.display.Stage;
import flash.display.Sprite;
import flash.net.URLVariables;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.navigateToURL;
public class Main extends Sprite
{
//------------------------------
// コンストラクタ
//------------------------------
public function Main()
{
sendData();
}
//------------------------------
// データ送信
//------------------------------
public function sendData():void
{
var variables:URLVariables = new URLVariables();
variables.title = "5ive.blog";
variables.url = "http://www.5ive.info/blog/";
variables.text = "PHPに複数のデータを渡す方法";
var urlRequest:URLRequest = new URLRequest();
urlRequest.url = "variables.php";
urlRequest.method = URLRequestMethod.POST;
urlRequest.data = variables;
//phpに送信
navigateToURL(urlRequest , "_self");
}
}
}
variables.php
ICC オープンスペースに行ってきた

前エントリーMake:Tokyo Meetingの後にはしごでICCに行きました。行く途中に3人で歩きながらの雑談。ワンセグを視聴すると字幕がついててびっくりとか、モバイル系の話とか、Felicaの非接触端末の話とか、FlashDevelopβ7出たねとか、iPotchで自作アプリ開発して遊んでるとか、いろいろ。
計算の庭
RFIDタグが仕込まれたカードを持って、計算しながらゲートをくぐって73になるようにゴールを目指す。非接触端末でのデータのやり取りはこれからおもしろくなりそう。
多義の森
Processingみたいなプログラミングモーション。これすごすぎ!1ピクセルの点が気持ちよく動いてて、ずーっと見ていられる。スクリーンセーバーとかにしたら絶対かっこいい。欲しい。
TENORI-ON
実機を初めて触った。思った以上に操作難しいかも。説明書見ないとルールが良く分かりません。
マイクロ・プレゼンス
地味に一番すごいと思ったかも。小さい昆虫をひたすらズームして見れるもの。すべての部位にピントをあわせるという新しい写真の技法を開発してるらしい。この画像処理のアルゴリズム知りたい。Flashでできないかな。
ICCには初めて行ったんだけど、結構見ごたえがあって面白かった。メディアアートとかインスタレーション好きにはお勧めですよ。ゲンさん、遠藤さん、お疲れ様でした。
Make:Tokyo Meetingに行ってきた




日曜日にMake:Tokyo Meetingに参加してきました。現地でゲンさんと合流。そして会場ではイメージソースの遠藤さんに偶然遭遇。三人で一緒に見て回ることに。グランドでは真空砲ぶっぱなしてキャベツ爆破とか、セグウェイに乗り回せたり。体育館では電子工作の作品展示や、GAINERワークショップとか基盤販売とか割とカオスな事になってました。工学部理系男子(眼鏡)が会場の9割を占めてて、Web系とはまた違った世界でした。あまりFlashな人たちはいなかったと思われ。
気になった作品はリアルのサウンドスペクトラムを可視化してたやつと、ウダーというオリジナル電子楽器(ミニ冷蔵庫がスピーカーになってて、コントローラーがかっこいい)で演奏してたやつ。全体的にマニアック過ぎたけどこれはこれでおもしろかったなぁと。その後3人でICCに向かいました。続きは次エントリーで。
あと、写真勝手に載せちゃいました。すいません。問題があれば連絡ください。
mouseChildrenとmouseEnabledについて
今更ながら知ったのでメモ。AS2でいうenabled = falseをしたくて調べたら、AS3ではもっと使い勝手が良くなっているようだ。
mouseEnabled
これはマウスイベントを受け取るかどうかを判断するプロパティ。こいつをfalseにするとマウスイベントを受け取らなくなるので、一時的にリスナーを切りたいけどremoveEventListenerするのが面倒とか、あるタイミングだけマウスに反応させたくない時に使用する。
mouseChildren
これと合わせて覚えておきたいのがmouseChildrenだ。mouseChildrenはオブジェクトの子に対してマウスが有効かどうかを判断するプロパティ。つまり親MCにぶらさがる子MCすべてのマウスイベントの伝播を止めることができる。一括してマウスイベントを受け取りたくない時に使うとかなりの手間が省ける。
mc.mouseEnabled = false;
こうするとmc以下のオブジェクトにマウスイベントが伝わらなくなるので便利ですよと。
REMOVEDとREMOVED_FROM_STAGEの違い
2つのイベントの違いで困惑したのでメモ。
REMOVED
自身、もしくは内包している子供のDisplayObjectがremoveChild()された時。
REMOVED_FROM_STAGE
自身がremoveChild()された時。タイミングとしてはREMOVED_FROM_STAGEの前に REMOVEDイベントが発生する。
RGBとCMYに色分解
画像処理の勉強としてRGBとCMYの色分解をやってみた。色々試したけどCMYKの4色に分解する方法がまだ良く分かんない。といことで画像処理入門の本をamazonで購入した。明日届いたらもうちょいやってみる。
パーティクルクラスを作ってみた
勉強用に自作で作ってみたので公開してみる。4月なので桜の花びらをパーティクルで散らしてみた。使い方はドキュメントクラスに下記のように記述する。
Main.as
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
import info.five.filters.Particle;
public class Main extends Sprite
{
private var p:Particle;
//------------------------------
// コンストラクタ
//------------------------------
public function Main():void
{
this.stage.addEventListener(MouseEvent.CLICK, onClick);
//-----[パーティクル]
p = new Particle("flower", this);
p.gravity = -0.2;
p.wind = -0.5;
}
private function onClick(e:MouseEvent):void
{
p.click();
}
}
}
まずはパーティクルインスタンスを作る。第1引数はパーティクルの元となるムービークリップのリンケージ名。第2引数はパーティクルを配置する場所。この場合はステージに配置するのでthisとする。インスタンスを作った後は各パラメータを指定する。gravityはマイナス値でパーティクルが上昇。windはマイナス値で左向きにパーティクルが流れる(0だと円状に広がる)。
p.gravity = -0.2;
p.wind = -0.5;
このサンプルではステージにクリックイベントを登録しているので、リスナー関数の中でp.click()を呼び出すことでクリックタイプのパーティクルを発動することができる。これをp.start()にするとパーティクルが生成され続ける。p.stop()で止める事ができる。
パーティクルクラスはこちら
Particle.as
{
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.utils.getDefinitionByName;
import flash.geom.Point;
public class Particle
{
private var container:DisplayObjectContainer;
private var linkage:String;
private var timer:Timer;
private var xVel:Number;
private var yVel:Number;
private var _vol:Number = 5;
private var _drag:Number = 0.99;
private var _shrink:Number = 0.95;
private var _gravity:Number = 0.8;
private var _fade:Number = 0.02;
private var _wind:Number = 0;
//------------------------------
// コンストラクタ
//------------------------------
public function Particle(s:String, targetContainer:DisplayObjectContainer)
{
linkage = s;
container = targetContainer;
}
//------------------------------
// パーティクルの生成
//------------------------------
private function makeParticle(e:Event):void
{
for (var i:uint = 0; i <_vol; i++)
{
var mc:MovieClip = new(getDefinitionByName(linkage));
container.addChild(mc);
var mouseX:int = container.stage.mouseX;
var mouseY:int = container.stage.mouseY;
var mousePt:Point = new Point(mouseX, mouseY);
var pt:Point = getNearPoint(mousePt);
mc.x = pt.x;
mc.y = pt.y;
mc.xVel = getRandRange( -5, 5);
mc.yVel = getRandRange( -5, 5);
mc.rot = getRandRange( -20, 20);
mc.addEventListener(Event.ENTER_FRAME, onRender);
}
}
//------------------------------
// 指定範囲からランダム値の取得
//------------------------------
private function getRandRange(min:Number, max:Number):Number
{
var randomNum:Number = (Math.random() * (max - min )) + min;
return randomNum;
}
//------------------------------
// 近似ポイント座標の取得
//------------------------------
private function getNearPoint(pt1:Point):Point
{
var len:uint = Math.round(Math.random() * 10);
var angle:uint = Math.round(Math.random() * 2 * Math.PI);
var pt2:Point = Point.polar(len, angle);
pt2.offset(pt1.x, pt1.y);
return pt2;
}
//------------------------------
// スタート
//------------------------------
public function start():void
{
container.stage.addEventListener(Event.ENTER_FRAME, makeParticle);
}
//------------------------------
// ストップ
//------------------------------
public function stop():void
{
container.stage.removeEventListener(Event.ENTER_FRAME, makeParticle);
}
//------------------------------
// クリック
//------------------------------
public function click():void
{
container.stage.addEventListener(Event.ENTER_FRAME, makeParticle);
timer = new Timer(300, 1);
timer.addEventListener(TimerEvent.TIMER, onDelay);
timer.start();
}
private function onDelay(e:TimerEvent):void
{
container.stage.removeEventListener(Event.ENTER_FRAME, makeParticle);
timer.removeEventListener(TimerEvent.TIMER_COMPLETE, onDelay);
}
//------------------------------
// レンダー
//------------------------------
private function onRender(e:Event):void
{
var mc:MovieClip = e.target as MovieClip;
if (mc.alpha> 0)
{
mc.x += mc.xVel + _wind * 10;
mc.y += mc.yVel;
mc.xVel *= _drag;
mc.yVel *= _drag;
mc.scaleX *= _shrink;
mc.scaleY *= _shrink;
mc.yVel += _gravity;
mc.alpha -= _fade;
mc.rotation += mc.rot;
}
else
{
mc.removeEventListener(Event.ENTER_FRAME, onRender);
mc.removeChildAt(0);
container.removeChild(mc);
mc = null;
}
}
//------------------------------
// getter setter
//------------------------------
public function get vol():Number { return _vol; }
public function set vol(value:Number):void {
_vol = value;
}
public function get drag():Number { return _drag; }
public function set drag(value:Number):void {
_drag = value;
}
public function get shrink():Number { return _shrink; }
public function set shrink(value:Number):void {
_shrink = value;
}
public function get gravity():Number { return _gravity; }
public function set gravity(value:Number):void {
_gravity = value;
}
public function get fade():Number { return _fade; }
public function set fade(value:Number):void {
_fade = value;
}
public function get wind():Number { return _wind; }
public function set wind(value:Number):void {
_wind = value;
}
}
}
不具合があれば、指摘していただけると嬉しいです。