Hi-farm blog

ActionScript 3.0 , AIR , FLEXからCocoa, OpenGL

2009年2月25日に開催された、第31回Flash OOP 勉強会に行ってきました。

�׋���̕��i

場所:

サイバーエージェントビル1F セミナースペース

4万円ほどで作れるマルチタッチディスプレイということで、マルチタッチのデバイスを自作して、ActionScriptをUIとして使っていました。
iPhoneとかで最近マルチタッチの話題が増えてきていたので、どの様にしてマルチタッチの機能を実現しているのか、実際の制作時の話しを含めて聞きたかったので行ってきました。

実現方法は、sakusan様のブログに説明していらっしゃいましたのでご興味のあるかた是非どうぞ。

簡単にはWebカメラで映像を受け取り、tbetaいうソフトが解析してsocketでAS3にタッチの情報を送る、という仕組みの様です。
AS3でタッチイベントを扱いやすくするためにMulti-Touchライブラリを自作されており、
・TouchManagerクラス:Touchを管理するクラス
・TouchEventクラス:触ったときに発生するイベント
・Fingerクラス:触った座標(0〜1の相対座標)、touchを一意にするためのIDを所有するクラス

を持っていて、TouchEventクラスのインスタンスがfingerを持っているので、Touchイベントが発生したときにイベントハンドラ内部で
e.finger.id
e.finger.x
e.finger.y
と記述することで触られた点を知る事ができるというものでした。(e = TouchEvent)

実際に触る時間がいっぱいあったので触ってみたのですが、

�f�B�X�v���C

でかい。

タッチ可能な領域が大きいということは、iPhoneの様にはいかず、タッチする人数が多くなる可能性があり、コンテンツを作るときに気にしないといけない問題が沢山あるのでどのようにタッチイベントの制御を行えばユーザーが意図した動きにるように作れるのかというのは結構難しい問題であるな、と感じました。
finger.idとタッチイベントが発生した座標をとって、或る程度の範囲内なら同じ人物の動作とみなすという判定が必要になるのかな?実際に作ったわけではないので想像でしかありませんが。

後は、このマルチタッチのデバイスを作ること自体が結構むずかしそうな気がしたので、どこかの段階でハードウェア屋さんと協力して新しいデバイスを次々と作る事ができると面白い展開があるのかも?とか想像していました。

このデバイスをみたり触ったりしているときに、感触を再現することができれば面白いなあなんて思ったのですが、これって音圧とか使うと少しは再現できたりするのかな?この辺の研究は一度やってみたいです。

この様なマルチタッチのデバイス+コンテンツを業務時間外で作り上げる力にはただひたすら感心するのみでした。本当にご苦労様でした。これからも面白いコンテンツを見せていただける事を楽しみにしています。
ってかうらやましいっす!

補足2:
サイバーエージェントさんって、こういうのも作ってたんですね。すてき。

��
  • 0 Comments
  • Filed under: Actionscript3
  • 本当にものすごく久々の投稿になってしまいました。

    先日、11/26に行われた、Spark勉強会で、Dynamic Sound Generationの発表をしてきたので、その資料をアップします。

    (※再生には音楽ファイルを必要なので、各自用意して下さい。)

    ソース一式

    PDF

    「フーリエ変換を使わない、エフェクトのかけかた」というタイトル通り、信号処理には本来フーリエ変換は欠かせないものですが、フーリエ変換の話しになると一気に敷居が高くなる(というか自分が今勉強している状態なので、この様な発表になりました。

     

    ただ、やはりフーリエ変換を使えていない&勉強途中での発表になってしまったので、波形が途切れてしまっているところがあるようで、ぷつぷつと途切れる音が結構聴こえてしまいます。。。

    あくまでご参考程度にしていただければと思います。

     

     

    [ファイル構成について]

     

    SoundGeneration.mxml:ラジオボタンやスライダーがついているView + 実際に音を鳴らすファイル

    model/SoundObj.as:Dynamic Sound Generationを使って音楽を再生したり、エフェクトをかけたりするスクリプトを記述しているファイル。

     

    SoundObj.asに関しては、mxmlでも使いやすいように、IMXMLObjectインターフェイスを実装しています。

     

    [SoundObj.asの仕組み]

    _currentEffectというプロパティを切り替えて、どのエフェクトをかけるのかを選択します。

     

    extractメソッドを呼び出すたびに、bufferプロパティにデータを蓄えています。

    これを使って、ディレイや逆再生を実現しています。

     

    なお、逆再生に関しては、こちらが大変参考になります。

    次は、フーリエ変換からめてしっかりとエフェクトをかけられるようになりたいなあ。
    フーリエ変換とエフェクトの掛け方を勉強できる機会があれば、是非参加したいです。

    [flash] Honda | AIRWAVE

    素敵なサイトを見つけました。

    バーチャルですが、ドライブデートができます。

    優れているな、と思ったのが、デートする中で、色々と操作をしなければいけないのですが、

    デートするなかで、温度調整など、何をするにはどこにあるものを触ればいいか、という手順が流れにそって理解できるようになっています。

    例えば、曲を変更するとき。

    女の子がこんな風に言ってきます。

     

    そういわれてムードを変えなきゃ男じゃあありません。早速変えようとしたときに、「+」表示されるので、

    曲を変えたいときにはここを操作すれば良いのか、とすんなりと知る事ができます。

     

    それにしても、ここに操作ボタンがあるのはいいですね。曲を頻繁に替える人にも使いやすそう。

    写真がズームされ、矢印をクリックすると曲を変える疑似体験ができます。

    COLTEMONIKAが入っているのは個人的にはうれしい。

     

    この様な操作をいくつか行うなかで、車の操作方法を覚えてます。

     

    そして、デートだけにロマンチックな方向へ。。。

     

    さて、何を送ろうかな。どきどきします。

    本気で考えた結果、1にしました。

    2はいきなりすぎるし、3はなあ。。

     

    と答えてた結果が最後に現れます。

    女の子とドライブするのなれてるとか言ってくれました。

    これだけでAIRWAVEを好きになりそうです。

    ですが、曲変更ボタンなど、車自体がとてもユーザビリティを考えて作られていることがこのサイトを体験する事で伝わりますし、何より僕には疑似デートっていうだけでドキドキしてました。

     

    ちなみに、僕がみた時は、デートモードもありました。

    試してみたいな。

  • 0 Comments
  • Filed under: Flash
  • いやーすごいですね!astro!

    ローカルへのファイル保存が可能だなんて!

    実際は、FileReferenceはローカルファイルを読み込んで直接操作できるみたいですが、ひとまず今回は保存です。

     

    サンプルはこちら。

    (Flashサンプル。赤丸をクリックすると、保存ダイアログが現れて、適当な名前を入力してボタンを押すと、保存。)

    注意点としては、同じファイル名で上書き保存しようとすると例外をはくらしいです。

    (これはもしかすると僕のサンプルが悪いだけかもです。。)

    corelibのJPGEncoderを使って、stageを画像として保存しています。

    ようは、FileReferenceにsaveというメソッドができて、それを使うと保存できるよ、ということです。

    ちなみに、保存できる形式は、

    String, XML, ByteArrayらしいです。

    今回のサンプルは、ByteArrayを使って保存しています。

     

    ちなみにソースはこんなのです。

     

    package
    {
    import com.adobe.images.*;
    import flash.display.*;
    import flash.events.*;
    import flash.net.*;
    import flash.utils.ByteArray;
    public class main extends MovieClip
    {
    private var jpg:JPGEncoder = new JPGEncoder(100);
    private var container:Sprite;
    private var bmpdata:BitmapData;
    private var btn:Sprite;
    private var fr:FileReference;
    public function main()
    {
    init();
    }

    private function init():void
    {
    //保存ダイアログを出すためのボタン。
    btn = new Sprite();
    btn.graphics.beginFill(0xff0000, 1);
    btn.graphics.drawCircle( 0, 0, 10);
    btn.graphics.endFill();
    addChild(btn);
    btn.width = btn.height = 10;
    btn.x = btn.y = 320;
    btn.addEventListener(MouseEvent.CLICK, onSave);
    fr = new FileReference();
    }
    private function onSave(e:MouseEvent):void
    {
    bmpdata = new BitmapData(400, 400, true);
    bmpdata.draw(stage);
    var ba:ByteArray = new ByteArray();
    // stageをBitmap化したものを、ByteArrayに変換。
    ba = jpg.encode(bmpdata);
    // 保存ダイアログを出す。
    fr.save(ba, “astroSavedFile.jpg”);
    }
    }
    }
    いや、ほんとにastroはDynamic Sound Generationといい、すごい進化してますね。

     

    [flash astro]Dynamic Sound Generation 2.

    またまたですが、Flash Player10 astroのDynamic Sound Generationです。

    ボタンを押すと、音が流れます。

    パルス波の長さを時間で変えています。

    注意:音を止める方法がないので、音を消したい場合はリロードして下さい。

     

    これがasだけでできるってのが素晴らしい!!

    今、個人的にはこの辺の機能が楽しいなあ。

     

    コードはこんなです。

    main.as

    <code>

    package
    {
    import flash.net.*;
    import flash.display.*;
    import flash.media.*;
    import flash.events.*;
    [SWF(backgroundColor="0xeeeeee", frameRate="50", stageHeight="200")]
    public class main extends Sprite
    {
    private var snd:Sound;
    private var square:Sprite;
    private var sh:Number = 200;
    private var btn1:Sprite;
    private var btn2:Sprite;
    private var btn3:Sprite;
    private var btn4:Sprite;
    private var btn5:Sprite;
    private var btn6:Sprite;
    public function main()
    {
    initBtn();
    }
    private function initBtn():void
    {
    btn = new Sprite();
    drawBtn(btn);
    btn.buttonMode = true;
    addChild(btn);
    btn.width = btn.height = 20;
    btn.x = 0;
    btn.y = 0;
    btn.addEventListener(MouseEvent.CLICK, click1);
    }
    private function drawBtn(sp:Sprite):void
    {
    sp.graphics.beginFill(0xff0000,1);
    sp.graphics.drawRect(0, 0, 20, 20);
    sp.graphics.endFill();
    }
    private function click1(e:MouseEvent):void
    {
    init();
    doSamplesCallbackHandler(1);
    }
    private function init():void
    {
    snd = new Sound();
    if( snd.hasEventListener(”samplesCallback”)) snd.removeEventListener(”samplesCallback”, samplesCallbackHandler);
    snd.addEventListener(”samplesCallback”, samplesCallbackHandler);
    snd.play();
    }
    private function samplesCallbackHandler(e:SamplesCallbackEvent):void
    {
    doSamplesCallbackHandler(1);
    }
    private var rate:Number = 44100;
    private var freq:Number = 440;
    private var phase:Number = 0;
    private var count:Number = 1;
    /**
    * generate wave data.
    */
    private function doSamplesCallbackHandler(type:int):void
    {
    //Voice.beep1();
    var freq:Number = 220;
    for( var i:uint=0; i < 512; i++ )
    {
    phase += freq/(rate);
    var arrange:Number = 1;
    var a:Number = 1;
    if( i%2==0 ) a = 1;
    arrange = a*count;
    var phaseAngle:Number = phase * arrange;
    var sample:Number = Math.sin(phaseAngle);
    //ここで波形をつくってます。
    sample = beep1(i);
    //左右チャンネルともに同じ波形。
    snd.samplesCallbackData.writeFloat(sample);
    snd.samplesCallbackData.writeFloat(sample);
    }
    delim++;
    if( delim > 256 ) delim = 0;
    }
    private var delim:Number = 0;
    /**
    * generate beep1
    * @param i:uint wave counter.
    * @return Number
    */
    private function beep1(i:uint):Number
    {
    var res:Number =0;
    //delim++;
    //if( delim > 256 ) delim = 0;
    //if( i < 256 ) res = 50;
    //else res = 0;
    if( i < delim ) res = 50;
    else res = 0;
    return res;
    }
    }
    }

    </code>

    えっと、ほんとは今日はパラグライダーで空を飛ぶ予定でしたが、天候により中止。

    で、代わりにastroのdynamic sound generationやってました。
    参考サイトはこちら:
    http://www.kaourantin.net/2008/05/adobe-is-making-some-noise-part-3.html
    http://memo.kappa-lab.com/2008/06/astroflash10_singing_do-re-mi–.html

    取りあえずソースは後ほどということで、サンプルだけ。

    http://www.hi-farm.net/astro/dynamicsound1.swf

    つまらないやつですが、マウスを押している間、音が高くなっていきます。
    マウスを放すと、音が低くなります。

    これをasのみでできるのは楽しいですね。
    デジタルシンセとか作れそう。

    もうちょっとソース整理したら改めて書きます!

    あー、デジタルシンセってか、サイン波の音とか、色々勉強したい事がふえるなあ。

    2008年6月9日00:53

    astro練習

    取りあえず、flash player10 astroの練習をしてみました。
    標準で3Dの機能がついたので、ひとまずちょっとしたサンプルを作成しました.

    http://www.hi-farm.net/astro/main.swf

    処理がかるくなるのかな?と思ってたのですが、Macのアクティビティモニタで見てみると、
    今までの様にPapervision3Dを作った時と、重さがあまりかわらない気がしたんですけど、どうなんでしょう?

    ソースはこれ。

    main.as—————————————-

    package
    {

    import flash.events.*;
    import flash.display.*;
    import flash.ui.*;

    [SWF(backgroundColor="0x000000", frameRate="50")]
    public class main extends MovieClip
    {

    private var container:Sprite;
    private var rect_vc:Vector.<Rect>;
    private var len:uint = 6;
    private var radius:Number = 100;
    private var container_vc:Vector.<Sprite>;
    private var innerLen:uint=15;

    public function main ()
    {
    init();
    }

    private function init():void
    {
    container_vc = new Vector.<Sprite>();

    container = new Sprite();
    container.x = 150;
    container.y = 10;

    addChild(container);
    rect_vc = new Vector.<Rect>();
    for( var i:uint=0; i < innerLen; i++ )
    {
    container_vc[i] = genCircle(0, 30*i+10,15*i);
    container_vc[i].rotationY = 30 * i;
    }
    addEventListener(Event.ENTER_FRAME, enterframeHandler);
    }

    private function genCircle(cX:Number, cY:Number, ra:Number):Sprite
    {
    var innerContainer:Sprite = new Sprite();

    for( var i:uint=0; i < len; i++ )
    {
    var rect:Rect = new Rect(0xffffff, 10, 10);
    innerContainer.addChild(rect);

    var rad:Number = (Math.PI/180) * ( (360/len)*i);
    rect.x = (Math.cos(rad) – Math.sin(rad)) * ra;
    rect.y = 0;
    rect.z = (Math.sin(rad) + Math.cos(rad)) * ra;
    rect_vc[i] = rect;
    }

    innerContainer.x = 0;
    innerContainer.y = 0;

    innerContainer.x = cX;
    innerContainer.y = cY;

    container.addChild(innerContainer);

    return innerContainer;
    }

    private function enterframeHandler(e:Event):void
    {
    for( var i:uint=0; i < innerLen; i++ )
    {
    container_vc[i].rotationY++;
    }
    }
    }
    }

    Rect.as—————————————-

    package
    {
    import flash.display.*;
    import flash.events.*;

    public class Rect extends Sprite
    {
    function Rect(col:uint, w:Number, h:Number)
    {
    this.graphics.beginFill( 0xffffff, 1);
    this.graphics.drawRect( 0, 0, w, h);
    this.graphics.endFill();
    }
    }
    }

    2008年6月1日02:36

  • 1 Comment
  • Filed under: Actionscript3, astro
  • 酔いそうになりました。

    見かけたこんなサイト。

    http://halo3.com/believe/shell.html

    まあ、多分、撮影をしっかりやって、FLVにして、コマ送りの操作をキーでさせてるというだけの仕組みとは思うのですが、
    これを見ていて、カメラが高いところから落ちるときに、酔いそうになりました。

    もともとジェットコースターとか本当にありえないくらい苦手な僕だからここまで過剰に反応したのだろうとは思いますが、これをフルスクリーンでやって、できればGainerかなんかでセンサーつけて、椅子(リクライニングするのでいいです)と連動できれば、簡易ジェットコースターにならん??なんて思ったのでした。

    しかも一家に一台!的に用意して。
    これでジェットコースターの練習ができる!という様な。

    作れるなら作りたいなあ。。

    2007年10月24日20:54

  • 0 Comments
  • Filed under: Flash