iPhoneでFlashを動かそう
![]()
2008-10-02(Thu) 16:37
![]()
投稿者: kisocci
FPS2008でご紹介したネタをもう少し細かくご紹介します。
Question. iPhoneにFlashPlayerはいまだ搭載されず残念ですが、知恵をしぼってiPhone「で」Flash「を」動かしてみたいと思います。
Answer. Papervision3Dで作ったiPhoneのFlashを実機iPhoneで動かしてみます。
■ iPhoneネイティブアプリ作り編
NDA
iPhone DeveloperのNDAに抵触する可能性がありそうなのであまりお話できません。レジストレーションしますと、サンプルプログラム等が見られます。加速度センサーのサンプルをもとに、x,y,zの値をXMLSocket形式のテキストでsocketに送出するようプログラムしましょう。socket部分は一般的なbds socketの実装で対応できます。
ここばかりはこれくらい。
■ Swift3D作り編
a.Swift3D ver5で直方体(「ボックス作成」)等からiPhoneの筐体を作ります。
お好みでベベルやテクスチャマップをしてください。
ポイント:マテリアルの名称やテクスチャの名称に日本語が含まれていると、Papervision3Dで表示されなくなりますので注意。名称を変更しておきましょう。
例:「ER-フラット-03」を「ER-Flat-03」に。
b. 完成したモデルを、Papervision3Dで扱えるdae形式ファイルとして書き出します。
Swift3D「ファイル」メニューの「シーンをPapervision3Dへとエクスポート…」を選択します。
ポイント:エクスポートに失敗するときがあります。Swift3Dを一度終了し、起動しなおして、あらためてt3dファイルを開き、(他の操作をせずに)続けてエクスポートする、のが確実なようです。
Flash作り編
c. ActionScript3.0でPapervision3Dを操ります。
Swift3Dよりエクスポートしたdaeファイルは次のようにしてモデルとして読み込みます。Papervision3Dの基礎はF-siteさんなどをご参考いただければ。
(要所抜粋)
//Papervision3Dのお約束。Scene3Dをつくります。
this.container = new Sprite();
addChild( this.container );
this.scene = new Scene3D( this.container );
//マテリアル定義にあらためて色を指定しています。
var myMaterialsList:MaterialsList = new MaterialsList();
myMaterialsList:MaterialsList.addMaterial ( new ColorMaterial (
0xffffff, 100 ), "ER_flatwhite");
myMaterialsList:MaterialsList.addMaterial ( new ColorMaterial (
0x000000, 100 ), "ER_blackmirror");
myMaterialsList:MaterialsList.addMaterial ( new ColorMaterial (
0x5B5B5B, 100 ), "ER_greymirror");
//iPhone.daeを読み込みます。
mCollada = new Collada("iPhone.dae", myMaterialsList:MaterialsList, 6);
//sceneに配置します。
scene.addChild( mCollada, "iphone" );
d. XMLを受け取る部分はXMLSocketとEventListenerを利用して作ります。
(要所抜粋)
//ソケットを開きます
private function openSocket():void {
socket = new XMLSocket();
configureListeners(socket);
socket.connect("192.168.0.2", 15000);
}
//ソケットのイベントリスナーを定義します。
private function configureListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.CLOSE, closeHandler);
dispatcher.addEventListener(Event.CONNECT, connectHandler);
dispatcher.addEventListener(DataEvent.DATA, dataHandler);
dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
}
//XMLSocketの受信イベント(DataEvent.DATA)ハンドラ
//XMLを解析し、accX,accY,accZに移動平均値を格納します。
private function dataHandler(event:DataEvent):void {
var i;
//移動平均のサンプル個数
var movingAveBufSize = 30;
//XMLオブジェクトの生成
rxml = new XML(event.data);
//X,Y,Z値のとりだし小数第二位でまるめています。
var x0 = Math.round(parseFloat(rxml.attribute("x"))*100)/100
var y0 = Math.round(parseFloat(rxml.attribute("y"))*100)/100
var z0 = Math.round(parseFloat(rxml.attribute("z"))*100)/100
//1G以上の発生は無視します。
if (Math.abs(x0)>1 || Math.abs(y0)>1 ||Math.abs(z0)>1 ) {
return;
}
//移動平均用バッファに追加します
accx_buf.push(x0);
accy_buf.push(y0);
accz_buf.push(z0);
//バッファサイズを超えたらバッファの最初(古いほう)から削除し、
//常にmovingAveBufSize個になるように。
if (accx_buf.length>movingAveBufSize) {
accx_buf.shift();
}
if (accy_buf.length>movingAveBufSize) {
accy_buf.shift();
}
if (accz_buf.length>movingAveBufSize) {
accz_buf.shift();
}
//移動平均値を求めます。
var ax = 0;
for(i=0; i < accx_buf .length; i++) {
ax += accx_buf[i];
}
accX = ax/accx_buf.length;
var ay = 0;
for(i=0; i < accy_buf.length; i++) {
ay += accy_buf[i];
}
accY = ay/accy_buf.length;
var az = 0;
for(i=0; i < accz_buf.length; i++) {
az += accz_buf[i];
}
accZ = az/accz_buf.length;
}
e. iPhoneモデルの動作はENTER_FRAMEで常に描画していきます。
...
this.addEventListener( Event.ENTER_FRAME, loop3D );
...
private function loop3D( event :Event ):void {
camerar += 0.02; //カメラを常に水平方向に回転させています
camera.x = 3000*Math.sin(camerar);
camera.z = 3000*Math.cos(camerar);
if( iphone )
{
//iphoneの傾きをアップデートします
updateObject( iphone );
}
//レンダリングします
this.scene.renderCamera( camera );
}
f. iphoneの傾きのアップデート(=updateObject()の中身。loop3Dより毎度よびだされます)
XML受信によって(+移動平均計算によって)常に更新されているaccX,accY,accZの値をもとに、傾きを計算します。角度を求める計算にはatan()を使います。
iphoneが正面に向かって倒れる角度(rotationX)は、ラフに言えば
iphone.rotationX = Math.atan(accY/accZ)*180/Math.PI;
とあらわせます。
iPhoneを液晶面を手前にしてたてたとき、加速度センサーの軸は左右がX(右が正)、上下がY(上が正)、前後がZ(手前が正)となります。
実際には座標系(回転の原点(0度の位置))を調整して、現物の傾きとあわせています。
if (accZ>0) {
iphone.rotationX = 90 - Math.atan(accY/accZ)*180/Math.PI ;
} else {
iphone.rotationX = 270 - Math.atan(accY/accZ)*180/Math.PI ;
}
if (accY>0) {
iphone.rotationZ = Math.atan(accX/accY)*180/Math.PI;
} else {
iphone.rotationZ = (-1)* Math.atan(accX/accY)*180/Math.PI;
}
■ 通信補足編
socket serverの準備
XMLSocketの中継のため、SocketServerが必要です。
ActionScript 3.0メモ
を参考にブロードキャストするだけでよいSocketServerを起動させておきます。
上記サイトを参考にするならば、ChatServer.javaとChatServerThread.javaが必要です。
crossdomain対策
FlashPlayer9のSocketセキュリティポリシー変更に対応するために、<policy -file-request>に
対処するサーバーをたてます。以下のruby版がよいでしょう。
古橋貞之の日記
trackback URL:
http://www.blocco-deli.co.jp/blog/2008/10/02/fps2008-1/trackback/
![]()
2008-10-21(,2,) 19:03 knlight
Hi, I’m working on how to send information from iphone to flash using xmlsocket. may you help me?
Here’s my email: z.knlight@gmail.com
Thanks a lot!
2008-10-21(,2,) 23:08 kisocci
Hi, knight
Thank you for reading our blog entry.
It’s my pleasure for your help.
Please ask your question feel free.
If you need, I’ll show you a socket source code
written in objective-c. ![]()
—
Takashi Kiso
2008-10-22(,3,) 12:56 knlight
Hi,Takashi Kiso
I try to send message to falsh using socket,but the flash client can’t read the message using xmlsocket.
I guess maybe it’s my iphone client problem.
So I really prefer the socket source code written in objetive-c.
Thanks a lot.
2008-10-23(,4,) 00:07 kisocci
OK. I’ll show you the source code via e-mail.
just moment please
2008-10-23(,4,) 12:37 knlight
ok~thx~
2009-03-18(,3,) 02:20 nunugera
Hi…I am doing a work very similar to yours…I am doing an 3d view for an object in flash and paper vision and i would like to know how can i do it…
?the program to install in the iphone?if there is any program to instal in pc or mac…I am already registered in iphone devcenter…Hope you can help me…thank you very much…
