ActionScript 3.0 , AIR , FLEXからCocoa, OpenGL
25 Feb
以前、名古屋のFxugにて少し発表した内容なんですが、ずっと記事にできてなかったので、今更ながらまとめます。
密かに前から社内用発表会のネタとして作ってはいたのですが、僕個人的にも、なかなか披露する機会がないまま、時間が過ぎてしまいました。
概要としては、
1. iPhone上でボタンをタップすると、AIR 2で作ったサーバーに、iPhoneからSocket経由で信号を送ります。
2. AIR 2のサーバーが、信号を受け取り、信号に応じた処理を行います。
これが作ったアプリのキャプチャです。
iPhoneとAIR 2サーバーの関係は、この通りです。
簡単に行ってしまえば、これだけです。
では、ここから説明します。
1. AIR 2のサーバー部分を作成
AIRでサーバーを作るには、UDPとTCPのサーバーがありますが、今回はTCPで通信するので、flash.net.ServerSocketクラスを使用します。
宣言〜受付開始
<pre>import flash.net.ServerSocket; // 接続してきたSocketを保持する var socks:Vector. = new Vector.(); // インスタンス生成 var server:ServerSocket = new ServerSocket(); // 接続時のイベントハンドラ作成 server.addEventListener(ServerSocketConnectEvent.CONNECT, serverSocketConnectHandler, false, 0, false); // 待ち受けポートを指定(43243番で受け付ける) server.bind(43243); // 待ち受け開始 server.listenen();</pre>
接続時:
function serverSocketConnectHandler(event:ServerSocketConnectEvent):void
{
// 接続してきたSocket
var socket:Socket = event.socket;
// 接続してきたSocketにデータを返すため、イベント設定
socket.addEventListener(ProgressEvent.SOCKET_DATA, receiveHandler, false, 0, false);
// 接続してきたSocketを保持する
socks.push(socket);
}
受信時:(本来は宛先を指定するべきだが、特に指定せず、全てのSocketに送信しています)
function receiveHandler(event:ProgressEvent):void
{
// データを送信したSocketを取得
var socket:Socket = event.target as Socket;
if(socket!=null) // nullチェック
{
// 受信データを取得
var recv:String = socket.readUTFBytes(socket.bytesAvailable);
// 操作対象のVideoPlayerを取得
var target:VideoPlayer = getCurrentVideo(); // 自作のメソッドです
// コマンドを取得し、操作を実行。コマンドを取得するため、indexOfを使っています。
if( recv.indexOf("prev") >= 0) {
setPos("prev");
} else if( recv.indexOf("next") >= 0) {
setPos("next");
} else if( recv.indexOf("play") >= 0) {
if( target.playing ) {
target.pause();
} else {
target.play();
}
}
}
}
AIRで作るサーバー周りは、こんなところです。エラー処理や切断時の処理などは書いてなくてごめんなさい。
iPhone側アプリケーションのSocket処理
では、次。iPhoneのほう。これも簡単な書き方でごめんなさいね。と、いうかCで最低限の実装しかしていないです。
TCPSendClient.m
接続:
-(void)connect:(NSString *)ip toPort:(NSInteger)port
{
if(_connected) // TCPSendClientが持っている、接続状態を保持する変数
{
return;
}
_connected = NO;
// IPアドレスを取得
servIP = [ip UTF8String];
// portを取得
servPort = port;
// socketが正しく生成できているかチェック
if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
NSLog(@"socket creation error.");
return;
}
// socketの設定
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(servIP);
servAddr.sin_port = htons(servPort);
// 接続
if(connect(sock, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0)
{
NSLog(@"connect error.");
return;
}
_connected = YES;
NSLog(@"connect succeed.");
}
送信:
-(void)send:(NSString *)message
{
mes = [message UTF8String];
mesLen = strlen(mes);
// 送信
if(send(sock, mes, mesLen, 0) != mesLen) {
NSLog(@"send failed.");
}
}
ちなみに、
TCPSendClientクラスは、Socket処理を受け持つクラスで、自作しています。
TCPSendClient.hはこんな風に書いています。
#import <Foundation/Foundation.h>
#import <stdio.h>
#import <sys/socket.h>
#import <arpa/inet.h>
#import <stdlib.h>
#import <string.h>
#import <unistd.h>
@interface TCPSendClient : NSObject {
int sock;
struct sockaddr_in servAddr;
unsigned short servPort;
const char *servIP;
const char *mes;
unsigned int mesLen;
BOOL _connected;
}
-(void)connect:(NSString *)ip toPort:(NSInteger)port;
-(void)send:(NSString *)message;
-(void)close;
-(BOOL)getConnected;
@property(readonly) BOOL connected;
@end
このサンプルでは、このようにTCPSendClientを使っています。
PagerViewController.m
-(IBAction) processConnect:(id)sender // ボタンをタップした時のAction
{
if([connectSwitch isOn]) // これは、接続のon/offを切り替えるUISwitchです。
{
[sendc connect:@"10.0.2.1" toPort:43243]; // sendcというのがTCPSendClientです
stateField.text = @"connect";
}
else
{
[sendc close]; // 本文では紹介しなかったですが、切断します。
stateField.text = @"disconnect";
}
}
データ送信:
-(IBAction) btnUp:(id)sender // 各ボタンのTouchUpInsideと関連づけています。
{
isPress = NO;
prevValue = 0;
if( (UIButton*)sender == btn) // btnとは、一つ前の動画にフォーカスをあてるためのボタンです。
{
dir = @"prev";
[sendc send:dir];
}
else if((UIButton*)sender == nextBtn) { // nextBtnとは、一つ次の動画にフォーカスをあてるためのボタンです。
dir = @"next";
[sendc send:dir];
}
else if((UIButton*)sender == playBtn) { // playBtnとは、フォーカスがあたっている動画を再生するためのボタンです。
dir = @"play";
[sendc send:dir];
}
}
ちなみに、こちらがiPhoneアプリの画面です。(すごい地味ですね。。。笑えない)
Interface Builderのキャプチャです。
Macをルーターにする
最後に、iPhoneとAIRサーバーを接続するための設定をします。Macなら「インターネット共有」を使えば簡単にルーターにして連携させる事が可能です。こういうときに、一つのメーカーが作っている事が良い事に思えますね。
今回は、AirMac経由で共有します。
1. 「システム環境設定」を開く
2. 「共有」を開く
3. 「インターネット共有」を選択する
4. 「共有する接続回路」がAirMac以外であることを確認。なっていなければ変更します。
→iPhoneとMacをAirMac(無線)で接続する
5. 「インターネット共有」のチェックを入れると、共有を開始するか確認してきますので、開始をクリックします。すると、画面右のAirmacのアイコンがこのようになります。
開始順としては、AIRサーバーとiPhoneが接続する必要があるので、
1. Macをルーターにする
2. AIRサーバーアプリを起動する
3. iPhoneアプリを起動して接続する。
4. iPhone上で操作する。
というところです。
今回簡単に紹介しすぎててすみません。このままでわかりにくいなどご意見ありましたら整理した上で、ソース込みで全て公開します。
30 Sep
久しぶりのブログ記事がメモレベルですみません。
Flash BuilderとFlashとを共存させたい場合、Flash Builder側にもflパッケージの場所を教えてあげたい場合があると思うのですが、なかなかこれが忘れやすいところにありますので、メモ代わりに残しておきます。
ちなみに、Snow Leopard, Flash CS4の環境です。
Application/Flash CS4/Common/Configuration/以下です。(Flash CS4の位置はインストールした場所により異なるでしょう)
.swcの中身は今イチ解らなかったのですが、
コンポーネント類 .swc : Components/以下
コンポーネント類のソース:Component Source/ActionScvript 3.0/以下
です。
もしかしたらもっと簡単に使えるようになる方法があるのかな、とも思いますが、ソースもみれるのはこれはこれでいい事があるかもしれないので残しておきます。
イージング系:libs/projects/Flash/src/以下
26 Feb
2009年2月25日に開催された、第31回Flash OOP 勉強会に行ってきました。

場所:
サイバーエージェントビル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)
実際に触る時間がいっぱいあったので触ってみたのですが、

でかい。
タッチ可能な領域が大きいということは、iPhoneの様にはいかず、タッチする人数が多くなる可能性があり、コンテンツを作るときに気にしないといけない問題が沢山あるのでどのようにタッチイベントの制御を行えばユーザーが意図した動きにるように作れるのかというのは結構難しい問題であるな、と感じました。
finger.idとタッチイベントが発生した座標をとって、或る程度の範囲内なら同じ人物の動作とみなすという判定が必要になるのかな?実際に作ったわけではないので想像でしかありませんが。
後は、このマルチタッチのデバイスを作ること自体が結構むずかしそうな気がしたので、どこかの段階でハードウェア屋さんと協力して新しいデバイスを次々と作る事ができると面白い展開があるのかも?とか想像していました。
このデバイスをみたり触ったりしているときに、感触を再現することができれば面白いなあなんて思ったのですが、これって音圧とか使うと少しは再現できたりするのかな?この辺の研究は一度やってみたいです。
この様なマルチタッチのデバイス+コンテンツを業務時間外で作り上げる力にはただひたすら感心するのみでした。本当にご苦労様でした。これからも面白いコンテンツを見せていただける事を楽しみにしています。
ってかうらやましいっす!
補足2:
サイバーエージェントさんって、こういうのも作ってたんですね。すてき。

29 Nov
本当にものすごく久々の投稿になってしまいました。
先日、11/26に行われた、Spark勉強会で、Dynamic Sound Generationの発表をしてきたので、その資料をアップします。
(※再生には音楽ファイルを必要なので、各自用意して下さい。)
「フーリエ変換を使わない、エフェクトのかけかた」というタイトル通り、信号処理には本来フーリエ変換は欠かせないものですが、フーリエ変換の話しになると一気に敷居が高くなる(というか自分が今勉強している状態なので、この様な発表になりました。
ただ、やはりフーリエ変換を使えていない&勉強途中での発表になってしまったので、波形が途切れてしまっているところがあるようで、ぷつぷつと途切れる音が結構聴こえてしまいます。。。
あくまでご参考程度にしていただければと思います。
[ファイル構成について]
SoundGeneration.mxml:ラジオボタンやスライダーがついているView + 実際に音を鳴らすファイル
model/SoundObj.as:Dynamic Sound Generationを使って音楽を再生したり、エフェクトをかけたりするスクリプトを記述しているファイル。
SoundObj.asに関しては、mxmlでも使いやすいように、IMXMLObjectインターフェイスを実装しています。
[SoundObj.asの仕組み]
_currentEffectというプロパティを切り替えて、どのエフェクトをかけるのかを選択します。
extractメソッドを呼び出すたびに、bufferプロパティにデータを蓄えています。
これを使って、ディレイや逆再生を実現しています。
なお、逆再生に関しては、こちらが大変参考になります。
23 Jul
さて、7.22はadobeにてspark勉強会でした。
会社を早めに出勤して、そうそうに向かったのですが、若干の遅刻。
やっぱり時間は苦手だなあ。
到着すると、Adobeの方からFlash Playerやpixel Benderなどの紹介がありました。
pixel Benderは是非試してみたいのですが、あいにく僕が持っているのはMacBookなので、まだ試す事はできなさそうです。。
MovieClipだけでなく、動画にもエフェクトがつけれるらしいですし、さらには噂では音にもエフェクトをつけられるという話しを聞いているので、とても興味があるのですが。。
Flash Player10は、Dynamic Sound Generationや、縦書きテキストの対応など、とても期待をしております。
ただ、いづれも最先端過ぎるのか、文献が少ないので習得するのは大変そうですね。
あと、FlashのSEO対策は、外部XMLとかも検索対象にしてくれるようだ、という話しを聞けたので、今後FlashはSEOに弱い!という通説が覆りそうで、楽しみです。
で、発表会。
はじめは、主催者でもある、yossy@beintaractiveさん。
Spark Projectの今までの経緯と、Actionscriptで疑似スレッドを実現する、ActionScript Thread Library 1.0 (そうめん)の紹介をされていました。
非同期処理を処理の流れ通りに記述できたり、割り込み処理や例外処理など、使いこなすとかなりASの開発が便利になりそうでした。
次は、seagirlさんの「Genius Framework」のご紹介。
シンプルで使い勝手が良さそうでした。Flexの方は一度触られてみてはいかがでしょうか?
あとは、コマンドラインでスケルトンコードを作ってくれる機能は、かなり便利なんじゃないかと思っています。
つぎは、mutsuさんのFrocessing。
テキストの扱いとか、3Dとかが比較的書きやすそうなのと、これで覚えれば本家Processingも使えるようになりそうですので、一度触ってみたいですね。
つぎは、arkwさん。
今まで全く考えていなかったような深い、深すぎるフレームについての話しが聞けて、すごく勉強になりました。
そして、最近Dynamic Sound Genrerationに興味を持っている僕が特に楽しみにしていた、
どこかでみたようなおもちゃから繰り出される音には、ただただ感激するのみでした。
勉強になります!
これがspark projectにコミットされているだなんて。すごいですね。
あまりにも文献が少ないサウンド系の情報を充実させよう!と思っていらっしゃるようです。
僕も何か力になれればと思うのですが、なかなか壁は高そうです。
サイトは、ksakaiさんの発表。
Swfを埋め込む時のタグについてや今後の方向性など、詳しいレベルでご説明いただいて、とても勉強になりました。
とってもためになる勉強会で、満足しつつ、2次会へ。
うーん。反省ですわ。。かなり気持ち悪い事を言っていたような気が。。。
しまった。
でも楽しかったです。
AIRとしょこたん。
なんか自分のやるべき事が見えた気がしました。
AIRでなんかしないとなあ。
お断り:
タグとかカテゴリーについては、無視して下さい。
9 Jul
えっと、今更なのですが、先日未来館にて開催されていた、エイリアン展に行ってきました。
ようするにエイリアンについての展示なのですが、さすが未来館というだけあって、見せ方がすごい。
これなのですが、大きな台(卓球台よりでかい)に上からプロジェクターを複数台使い、画面を作ります。
で、台の上に映しだされているボタンをタッチすると、実際にタッチしたことになり、新しいコンテンツを開くことができます。
※上下逆さまでごめんなさい。
職員さんをつかまえて強引に仕組みを聞いてみたのですが、
なんでも、この仕組みは、台に静電気センサーを仕込み、複数同時タッチに対応しているようです。
ちなみに、静電気センサーは調べたところ、15万くらい?でした。
静電気センサーについては、こちらが詳しいです。
さらに最後には、「宇宙空間にメッセージを送ろう!」という事で、トラックボールを使ったりして、メッセージの組み合わせを選ぶことができます。
で、写真を撮って、メッセージと同時に大画面に表示されます。
ちと恥ずかしいね。
Flashでやるなら、Gainer(Funnel?)と絡めたりするんでしょうね。
ここまで大がかりなものを作る事ができたら楽しいだろうなー。
26 Jun
いやーすごいですね!astro!
ローカルへのファイル保存が可能だなんて!
実際は、FileReferenceはローカルファイルを読み込んで直接操作できるみたいですが、ひとまず今回は保存です。
サンプルはこちら。
(Flashサンプル。赤丸をクリックすると、保存ダイアログが現れて、適当な名前を入力してボタンを押すと、保存。)
注意点としては、同じファイル名で上書き保存しようとすると例外をはくらしいです。
(これはもしかすると僕のサンプルが悪いだけかもです。。)
corelibのJPGEncoderを使って、stageを画像として保存しています。
ようは、FileReferenceにsaveというメソッドができて、それを使うと保存できるよ、ということです。
ちなみに、保存できる形式は、
String, XML, ByteArrayらしいです。
今回のサンプルは、ByteArrayを使って保存しています。
ちなみにソースはこんなのです。
25 Jun
またまたDynamic Sound Generationです。
これは、mouseXの値をもとに、音程を変えるというサンプルです。
ちなみに、音のもとになるのはぜんかいのと同じ矩形波を使っています。
ソースは後ほど。
23 Jun
今回は色々とサンプルをつくってみながら書いてみます。
波形には色々とあるようですが、今回は、矩形波をいじってみました。
基本的なのは、これ。
ちなみに、512ってのはおまじないと思って下さい。
※サンプルFlash(音がなります。しかも制御できません。)

で、矩形の周期を半分にすると、こうなります。
※サンプルFlash(こちらも音がなります。もちろん制御はできないです。)

二つを聴き比べると、二つ目(周期が短い方)が音が高いですよね。
どうやら、周期が短いほど音が高くなる、という仕組みらしいです。
と、いうことは、この周期を徐々に短くしていくと、どうなるんでしょう?
※サンプルFlash(音がなり、制御不能。今までと同様ですね。)
うんうん。
ということは、これらをうにょうにょすると、宇宙っぽくできるかな?Perfumeっぽい音が出せるかな?○タヤスタカ的な音をasだけで出す事ができるのかな?
次は他のタイプの波形をいじってみようと思います。
あ、それぞれのサンプルASも.txtとしてリンク貼っておくのでよかったらいじって下さいね。(ごめんなさい。コメントつけれてないです)
13 Jun
またまたですが、Flash Player10 astroのDynamic Sound Generationです。
ボタンを押すと、音が流れます。
パルス波の長さを時間で変えています。
注意:音を止める方法がないので、音を消したい場合はリロードして下さい。
これがasだけでできるってのが素晴らしい!!
今、個人的にはこの辺の機能が楽しいなあ。
コードはこんなです。
main.as
<code>
</code>