以前の記事でご紹介した「Flash CS5に潜む謎のクラスWorld」は、非ドキュメントの物理エンジンに含まれているようです。昨年11月に書かれた英文blogに、ライブラリの中身を探った解説がありました。そのblogのテスト用コードをもとに、簡単なサンプルをつくってみました。
参考にしたのは、Significant Data「Flash CS5 Built-in Physics Discovered」です。スクリプトはFlash Professional CS5でしか書出せず、CS5.5でもコンパイルエラーになります。またもちろん、正規サポートはされません。
以下のスクリプト001をFlash Professional CS5のフレームアクションとしてコピー&ペーストします。ステージには何も置きません。[ムービープレビュー]でステージをクリックすると、ランダムに置かれたインスタンスの半分が落下運動をします。
図001■ランダムに置かれたインスタンスの半分が落下運動する→ |
→ |
const COUNT:uint = 50; var instances:Vector.<Shape> = drawShapes(COUNT); var physics:PhysicsManager = new PhysicsManager(stage); var myWorld:World = physics.createWorld(); assignPhysics(); myWorld.enableCollisions(true); myWorld.setGravity(new Point(0, 200)); stage.addEventListener(MouseEvent.CLICK, startPhysics); function startPhysics(eventObject:MouseEvent):void { addEventListener(Event.ENTER_FRAME, animatePhysics); } function assignPhysics():void { var myPoint:Point = new Point(1, 1); for (var i:uint = 0; i < COUNT; i++) { var instance:DisplayObject = instances[i]; var physicsObject:PhysObj = myWorld.addPhysObj(instance, myPoint, 0, false); if (i % 2) { physicsObject.setNonMoving(true); } } } function animatePhysics(eventObject:Event):void { myWorld.updateAllObjects(); myWorld.step(); } function drawShapes(count:uint):Vector.<Shape> { var nStageWidth:int = stage.stageWidth; var nStageHeight:int = stage.stageHeight; var nWidth:Number = 25; var nHeight:Number = 5; var instances:Vector.<Shape> = new Vector.<Shape>(count); for (var i:uint = 0; i < count; i++) { var myShape:Shape = new Shape(); var myGraphics:Graphics = myShape.graphics; myGraphics.beginFill(uint(0xFFFFFF * Math.random())); myGraphics.drawRect(-nWidth / 2, -nHeight / 2, nWidth, nHeight); myGraphics.endFill(); addChild(myShape); instances[i] = myShape; myShape.x = nStageWidth * Math.random(); myShape.y = nStageHeight * Math.random(); myShape.rotation = 360 * Math.random(); } return instances; }
非ドキュメントの機能ですので、ごく簡単にだけご説明します。まず、関数drawShapes()はタイムラインにShapeインスタンスをランダムにつくったうえで、Vectorオブジェクト(Shapeベース型)に納めて返します。試す手間がかからないように、スクリプトで配置しただけで、物理エンジンの中身には関わりません。前出のblogではMovieClipインスタンスを[ライブラリ]から配置しています。
物理エンジンのシミュレーションは、PhysicsManagerインスタンス(physics)からPhysicsManager.createWorld()メソッドにより件のWorldインスタンス(myWorld)をつくるところから始まります。
そして、タイムラインに置いたDisplayObject(Shape)インスタンスをWorld.addPhysObj()メソッドによりPhysObjオブジェクトとして加え、PhysObj.setNonMoving()メソッドで動かすかどうかを定めます。
さらに、メソッドWorld.enableCollisions()で衝突判定、World.setGravity()で重力を設定します。あとは、DisplayObject.enterFrameイベントで、World.updateAllObjects()とWorld.step()メソッドを呼出すことにより自然落下のアニメーションが行われます。
前出英文blogに引用のビデオに示されたとおり、Adobe MAX 2009ではインバース・キネマティクスのフレームワークに含まれる物理エンジンを[物理]パネルとともに公開する予定でした。しかし、製品でその公開は実現せず、非ドキュメントのクラスとして残ったようです。
内部的に物理エンジンはあるはずですが、CS5.5ではもはやアクセスも許されなくなったのでしょう。できれば、次期バージョンで公開してもらいたいものです。
物理エンジンのAPIは、ライブラリPffLib.swcとしてFlash Professional CS5のアプリケーションの中に含まれています。これをコピーすれば、CS5.5でも使えるようです。もちろん、サポート外であることは変わりません。
具体的には、アプリケーションのAdobe Flash CS5/Common/Configuration/ActionScript 3.0/libsフォルダにPffLib.swcがあります(図002)。
図002■Flash Professional CS5アプリケーション内のPffLib.swc
このPffLib.swcをディスクの任意の場所(下図003ではユーザーのフォルダmylibs/libsとした)にコピーします。そして、CS5.5の[パブリッシュ設定]から[ActionScript 3.0の詳細設定]ダイアログボックスを開き、[ライブラリパス]にPffLib.swcがあるフォルダを加えます(図003)。
図003■CS5.5の[ActionScript 3.0の詳細設定]ダイアログボックスで[ライブラリパス]を追加
筆者の環境では、これでCS5.5でも前掲スクリプト001が動作しました。なお、あくまで自己責任でお楽しみください。