Progressionのコンポーネントスタイルで使えるアニメーションのエフェクトをクラススタイルでも使えるようなので、試しに使ってみました。

以下の10種類があります。
  • BlindsEffect ・・・ ブラインドのようなマスク
  • FadeEffect ・・・ フェードイン
  • FlyEffect ・・・ 指定した方向からスライド
  • IrisEffect ・・・ 正方形または円形マスクをズーム
  • PhotoEffect ・・・ 写真のフラッシュのように表示
  • PixelDissolveEffect ・・・ チェッカーボードのパターンでランダムに表示
  • RotateEffect ・・・ ムービークリップを回転
  • SqueezeEffect ・・・ ムービークリップを拡大・縮小
  • WipeEffect ・・・ マスクを水平移動
  • ZoomEffect ・・・ ムービークリップを縦横比を維持しながら拡大・縮小


使い方は下記のようにクラスを作って継承するか、new BlindsEffect()でもOK。
このクラスオブジェクトをAddChild、RemoveChildすることにより、エフェクトが開始されます。
	public class BlindsComp extends BlindsEffect {
		
		public function BlindsComp(initObject = null) {
			
			super(initObject);
			
			duration = 0.5;
			easing = Circular.easeOut;
			dimension = EffectDimensionType.HORIZONTAL;
			numStrips = 20;
			
		}
		
	}


動きのサンプル:


いちおうソースを。
Progression4は含まれてませんので、公式ページよりダウンロードしてください。
trackbacks(1) comments(0)

このサイトを見てて、
Google Maps API for Flashにストリートビュー機能があるのかなーと思って調べたのですが、
どうやら通常のGoogle Maps APIのストリートビュー機能と連携を取っているようですね。

GoogleCodeのDemo Galleryにもある、以下のサイトで詳しく説明されてました。
Making Components Work Together | InsideRIA
ソースも載っているので非常に分かりやすいです。今回は、ストリートビューのパノラマとFlashのマーカーの位置を同期するように改良しました。
位置情報はExternalInterfaceを使ってFlashとJSでやり取りします。

こちらデモ。

ActionScript:

package {
	
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.external.ExternalInterface;
	
	import com.google.maps.Map;
	import com.google.maps.LatLng;
	import com.google.maps.MapType;
	import com.google.maps.MapEvent;
	import com.google.maps.MapMouseEvent;
	import com.google.maps.controls.MapTypeControl;
	import com.google.maps.controls.PositionControl;
	import com.google.maps.controls.ZoomControl;
	import com.google.maps.controls.ZoomControlOptions;
	import com.google.maps.overlays.Marker;
	import com.google.maps.overlays.MarkerOptions;
	
	public class StreetViewEx extends Sprite {
		
		private var Gmap:Map = new Map();
		private static const API_KEY:String = "YOUR_API_KEY";
		private var marker : Marker;
		
		public function StreetViewEx() {
			
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.stageFocusRect = false;
			
			//JS呼び出し用
			if (ExternalInterface.available) {
				ExternalInterface.addCallback("setMarker", setMarker);
			}
			
			//初期値
			Gmap.key = API_KEY;
			Gmap.language = "ja";
			Gmap.setSize(new Point(stage.stageWidth, stage.stageHeight));
			
			//コントロール追加
			Gmap.addControl(new PositionControl());
			Gmap.addControl(new ZoomControl(new ZoomControlOptions( { hasScrollTrack: false } ) ));
			Gmap.addControl(new MapTypeControl());
			
			Gmap.addEventListener(MapEvent.MAP_READY, onMapReady, false, 0, true);
			Gmap.addEventListener(MapMouseEvent.CLICK, onMapClick);
			
			addChild(Gmap);
			
		}
		////////////////////////////////////////////////// マップ調整
		private function onMapReady(event:MapEvent):void {
			
			Gmap.removeEventListener(MapEvent.MAP_READY, onMapReady);
			Gmap.setCenter(new LatLng(35.658918,139.745857), 16, MapType.NORMAL_MAP_TYPE);
			
			var markerOpt:MarkerOptions = new MarkerOptions();
			markerOpt.draggable = true;
			
			marker = new Marker( new LatLng(35.65887, 139.745954), markerOpt );
			marker.addEventListener(MapMouseEvent.DRAG_END, onMarkerRelease);
			
			Gmap.addOverlay( marker );
			
		}
		////////////////////////////////////////////////// マーカー離した時、パノラマ更新
		private function onMarkerRelease(event:MapMouseEvent):void {
			
			ExternalInterface.call( "setPanorama", event.latLng.lat(), event.latLng.lng() );
			
		}
		////////////////////////////////////////// マップクリック、マーカー移動、パノラマ更新
		private function onMapClick(event:MapMouseEvent):void {
			
			marker.setLatLng( event.latLng );
			ExternalInterface.call( "setPanorama", event.latLng.lat(), event.latLng.lng() );
			
		}
		////////////////////////////////////////////////// JSよりマーカー位置調整
		public function setMarker(lat:Number, lng:Number):void {
			
			marker.setLatLng( new LatLng(lat, lng) );
			
		}
	}
}


JavaScript:

var myPano;   
var panoClient;
//ビュー初期化
function initialize() {

	var myLatLng = new GLatLng(35.658918,139.745857);
	var myPOV = {yaw:180,pitch:0};

	myPano = new GStreetviewPanorama(document.getElementById("pano"));
	myPano.setLocationAndPOV(myLatLng, myPOV);
	
	panoClient = new GStreetviewClient();
	panoClient.getNearestPanorama(myLatLng, showPanoData);
	
	//新しい場所に移動した場合
	GEvent.addListener(myPano, "initialized", changePanorama);

}
//swfに送信
function changePanorama(location) {

	if(navigator.appName.indexOf("Microsoft") != -1){
		window.flamap.setMarker(location.lat,location.lng);
	}else{
		document.flamap.setMarker(location.lat,location.lng);
	}
	
}
//移動
function showPanoData(panoData) {

	if (panoData.code != 200) {
		GLog.write('showPanoData: Server rejected with code: ' + panoData.code);
		return;
	}
	myPano.setLocationAndPOV(panoData.location.latlng);
	
}
//swfから受信
function setPanorama( lat, lng ) {
	
	panoClient.getNearestPanorama(new GLatLng(lat, lng), showPanoData);

}


SWF書き出し部分:

<div id="flashArea">
    <object
      classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
      codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"
	  width="600"
	  height="250"
	  id="flamap">
      <param name="movie" value="StreetViewEx.swf">
      <param name="quality" value="high">
      <param name="flashVars" value="key=YOUR_API_KEY">
      <embed
		name="flamap"
        width="600"
        height="250"
        src="StreetViewEx.swf"
        flashVars="key=YOUR_API_KEY"
        quality="high"
        pluginspage="http://www.macromedia.com/go/getflashplayer"
        type="application/x-shockwave-flash">
      </embed>
    </object>
</div>
<div id="pano" style="width:600px;height:250px;"></div>

ソース一式
※ソース内「YOUR_API_KEY」は取得したAPIキーを入れてください。
※ExternalInterfaceを使う際の注意として、「ExternalInterfaceにハマる - Nega Diary」を参考に、
html中に挿入したswfに対して、objectには、idを、embedにはname属性を付け、その名前を用いて、swf中の関数にアクセスする。

参考サイト
Google Maps API ActionScript Reference
Google Maps API リファレンス
Making Components Work Together - Making Components Work Together | InsideRIA
Google Maps API for Flash で地図を作る - イナヅマtvログ

trackbacks(0) comments(0)

Progressionではシーンを用意しておけばGotoコマンドで移動できるのですが、
シーン毎に処理を変えたい場合など、ドコにいったかを把握しておきたい場合などありますよね。
↓そんな時はProcessEventを使うと良いらしいとのことなのでテスト。
「Progression3都物語...」- blog.naggg.jp

ProcessEventには以下のものがあります。
・PROCESS_COMPLETE
・PROCESS_ERROR
・PROCESS_EVENT
・PROCESS_INTERRUPT
・PROCESS_SCENE
・PROCESS_START

IndexScene内で以下コードを追加してどのタイミングで呼ばれているかチェックしてみます。

IndexScene.as

		public function IndexScene() {

			progression.addEventListener(ProcessEvent.PROCESS_EVENT, onEvent);
			progression.addEventListener(ProcessEvent.PROCESS_SCENE, onEvent);
			progression.addEventListener(ProcessEvent.PROCESS_START	, onEvent);
			progression.addEventListener(ProcessEvent.PROCESS_INTERRUPT, onEvent);
			progression.addEventListener(ProcessEvent.PROCESS_ERROR, onEvent);
			progression.addEventListener(ProcessEvent.PROCESS_COMPLETE, onEvent);

		}

		private function onEvent(event:ProcessEvent):void {
			
			trace("ProcessEvent >>>>>>>> type:"+event.type, ",sceneId:"+event.scene.sceneId+"\n");
			
		}


trace結果([/index]→[/index/scene1]に移動の場合):
[LOG] シーン移動を開始, 目的地 = /index/scene1
ProcessEvent >>>>>>>> type:processStart ,sceneId:/index

[LOG] /index シーンの goto イベントを実行。
ProcessEvent >>>>>>>> type:processEvent ,sceneId:/index

[LOG] /index/scene1 シーンに移動。
ProcessEvent >>>>>>>> type:processScene ,sceneId:/index/scene1

[LOG] /index/scene1 シーンの load イベントを実行。
ProcessEvent >>>>>>>> type:processEvent ,sceneId:/index/scene1

[LOG] /index/scene1 シーンの init イベントを実行。
ProcessEvent >>>>>>>> type:processEvent ,sceneId:/index/scene1

[LOG] シーン移動を完了。
ProcessEvent >>>>>>>> type:processComplete ,sceneId:/index/scene1
※Index.asにある開発者用の出力を有効にしてます。

まず頭でprocessStartが来て最後にprocessCompleteが送出されます。
各シーンのSceneEventの度にprocessEventも送出されます。
processInterruptは途中中断した時、processErrorは移動シーンが無かった場合に送出されるようです。

移動後に処理を分けたい場合はprocessCompleteのリスナーでevent.scene.sceneIdまたはevent.scene.idを利用して分けるのがよさそうです。

以下、シーン毎にナビゲーションボタンをオン・オフにしてみたサンプルです。
プレビュー | ソース

trackbacks(1) comments(0)
シーンを追加する時にその度addSceneしてもいいのですが、大量にある場合などとても面倒なので、スマートに作れる方法を探ってみました。


PRMLLoaderで作成
PRMLLoaderクラスは、PRML形式のXMLファイルから自動的に、Progressionインスタンスを作成できます。
PRML形式のXMLについてはPRML リファレンスを参照ください。
仕様に沿って以下のようなXMLを作ります。

prml.xml

<?xml version="1.0" encoding="utf-8"?>
<prml version="2.0.0" type="text/prml">
	<scene name="index" cls="myproject.IndexScene" title="index">
		<scene name="scene1" cls="myproject.templates.MyScene" title="scene1"></scene>
		<scene name="scene2" cls="myproject.templates.MyScene" title="scene2"></scene>
		<scene name="scene3" cls="myproject.templates.MyScene" title="scene3"></scene>
		<scene name="scene4" cls="myproject.templates.MyScene" title="scene4"></scene>
		<scene name="scene5" cls="myproject.templates.MyScene" title="scene5"></scene>
		<scene name="scene6" cls="myproject.templates.MyScene" title="scene6"></scene>
		<scene name="scene7" cls="myproject.templates.MyScene" title="scene7"></scene>
		<scene name="scene8" cls="myproject.templates.MyScene" title="scene8"></scene>
		<scene name="scene9" cls="myproject.templates.MyScene" title="scene9"></scene>
		<scene name="scene10" cls="myproject.templates.MyScene" title="scene10"></scene>
	</scene>
</prml>

Progressionの各シーン毎に<scene>~</scene>を作り、name・cls・title属性を設定します。
このXMLをIndex.as内でロードします。

Index.as

	public class Index extends CastDocument {

		//宣言しないとエラーでます。
		IndexScene;

		public function Index() {

		}
		protected override function _onInit():void {
			
			// stage の初期設定を行います。
			align = StageAlign.TOP_LEFT;
			quality = StageQuality.HIGH;
			scaleMode = StageScaleMode.NO_SCALE;
			
			// SWFWheel を有効化する
			SWFWheel.initialize( stage );

			var loader:PRMLLoader = new PRMLLoader( stage, new URLRequest( "prml.xml" ) );
			loader.addEventListener(Event.COMPLETE, 
				function (e:Event):void {
					
					//読み込み完了時の処理
					trace( loader.progression.root.toXMLString() ); 
					
				}
			);

		}
	}


IndexScene.as

	public class IndexScene extends SceneObject {

		//宣言しないとエラーでます。
		MyScene;

		public function IndexScene() {

		}

(以下略)


PRMLLoaderクラスはXML読み込み、Progressionインスタンス作成、最初のシーンに移動と自動でやってくれます。
今回scene1~scene10は同じテンプレートを使用していて、MySceneクラス内でinitObjectを受け取れなくて困ったのですが、以下のようにすると受け取れるようです。

prml.xmlでsceneの子ノードにタグを追加する。

<?xml version="1.0" encoding="utf-8"?>
<prml version="2.0.0" type="text/prml">
	<scene name="index" cls="myproject.IndexScene" title="index">
		<scene name="scene1" cls="myproject.templates.MyScene" title="scene1">
			<id>1</id>
		</scene>
		<scene name="scene2" cls="myproject.templates.MyScene" title="scene2">
			<id>2</id>
		</scene>

(以下略)


受け取る側のMySceneクラスでは_onLoad等のタイミングで「sceneInfo.data」を取得できます。
sceneInfo.dataって?XMLUtil?と思った方は第5回 Progression3でWebサイトを作る(後編)を参考ください。

MyScene.as

		protected override function _onLoad():void {

			//Objectに変換。<id>~</id>がobj.idに。
			var obj:Object = XMLUtil.xmlToObject( new XMLList( sceneInfo.data ) );
			trace(obj.id);
	
		}


これで各シーンで表示を切り替えたりできますね。



LoadURL+addSceneFromXMLで作成
PRMLLoaderが一気にProgressionインスタンスを作ってくれるのに対して、addSceneFromXMLはXMLを渡すとシーンを追加してくれます。
XMLを読み込むところはLoadURLを利用します。各シーンでそれぞれ別のXMLから子シーンを追加したりできます。
とりあえず先ほどのPRMLLoaderと同じprml.xmlを追加してみます。

Index.asに追加する場合

		protected override function _onInit():void {
			
			// stage の初期設定を行います。
			align = StageAlign.TOP_LEFT;
			quality = StageQuality.HIGH;
			scaleMode = StageScaleMode.NO_SCALE;
			
			// SWFWheel を有効化する
			SWFWheel.initialize( stage );
			
			// 開発者用の出力を有効化します。
			//Verbose.enabled = true;
			//Verbose.filteringCommand();
			
			// Progression インスタンスを作成します。
			prog = new Progression( "root", stage );
			
			// ブラウザ再生時に URL 同期を有効化します。
			prog.sync = true;
			
			prog.root.onLoad = function():void {
				this.addCommand(
					new LoadURL( new URLRequest( "prml.xml" ) ),
					function () : void {
						prog.root.addSceneFromXML( new XML(this.latestData) );
					}
				);
			}
			prog.goto( new SceneId("/root/index" ));
			
		}


IndexScene.asに追加する場合

		protected override function _onLoad():void {
			addCommand(
				new LoadURL( new URLRequest( "prml.xml" ) ),
				function () : void {
					addSceneFromXML( new XML(this.latestData) );
				}
			);
		}




For文でシーン作成
For文で普通に繰り返し作成です。
この場合、SceneObjectにnameとinitObjectを渡すことができます。

IndexScene.as

		public function IndexScene() {
			
			title = "index";
			_page = new IndexPage();
			
			//For文でシーン作成
			for (var i:int = 1; i <= 10; i++ ) {
				
				var sceneInit:Object = { id : i };
				addScene( new MyScene ("scene" + i, sceneInit ) );
				
			}
			
		}



この場合、直感的になにをしているか分かりやすいかもしれません。
いろいろな方法があると思いますが、サイトの規模などを考慮して、やりやすい方法で作成するのがいいと思います。

trackbacks(0) comments(0)
仕事でモバイルのFlash待ち受けを作る機会があったので、忘れないよう書いておきます。

基本設定
・容量は100KB以内で書き出す
・フレームレートは8~12fpsが妥当
・待受サイズは240x320pxが多い。他サイズも考慮して背景などを広めにとっておく


変数にアクセス
スラッシュシンタックスと (/) コロン (:) を組み合わせて使用。
例)メインタイムラインの car 変数。
/:car

例)メインタイムラインにあるムービークリップインスタンス mc1 にネストされたムービークリップインスタンス mc2 の car 変数。
/mc1/mc2/:car


tellTarget()
ムービークリップを制御する場合に以下のように使用する
 tellTarget("ball") {
  gotoAndPlay(2);
 }


日付・時計
 today = fscommand2("GetDateDay"); // 1 ~ 31
 weekday = fscommand2("GetDateWeekday");// 0 ~ 6
 thisMonth = fscommand2("GetDateMonth"); // 1 ~ 12
 thisYear = fscommand2("GetDateYear"); // 0 ~ 9999
 hour = fscommand2("GetTimeHours");// 0 ~ 23
 minutes = fscommand2("GetTimeMinutes");// 0 ~ 59
 seconds = fscommand2("GetTimeSeconds");// 0 ~ 59


バッテリー
 battLevel = fscommand2("GetBatteryLevel");// 0 ~ GetMaxBatteryLevel


電波状態
 sigLevel = fscommand2("GetSignalLevel");// 0 ~ GetMaxSignalLevel


充電中かどうか
 myPower = fscommand2("GetPowerSource");
//0: デバイスはバッテリー電源で動作している 
//1: デバイスは外部電源で動作している


繰り返しアクションを実行する場合
enterFrameのような便利なものがないので、フレーム1に実行するアクションを書いたら、フレーム2にgotoAndPlay(1);で繰り返す。

各キャリアのスペック
NTTドコモ
au
SoftBank

trackbacks(0) comments(0)
ブラウザのアドオンとしてカスタムしたGoogleツールバーを配布するときのメモです。
Googleツールバーのインストールはこちらから。
API一覧をみながらXMLをつくります。

・Google ツールバー API
http://toolbar.google.com/buttons/intl/ja/apis/index.html

で、今回つくったXMLは以下になります。
<?xml version="1.0" encoding="utf-8"?>
<custombuttons xmlns="http://toolbar.google.com/custombuttons/">
<button>
<site>http://plug.heteml.jp/motulog/</site>
<title>motuLog</title>
<feed refresh-interval="3600">http://plug.heteml.jp/motulog/rss.xml</feed>
<description>For Developers</description>
<search>http://plug.heteml.jp/motulog/mt-search.cgi?search={query}&amp;fulltext=Search</search>
<icon mode="base64" type="image/x-icon">
R0lGODlhEAAQAJEAAAAAADMzM////wAAACH5BAAAAAAALAAAAAAQABAAAAIrjI9pwO2+nmRxvmob
zmBnb4GTKJFX0AgpILRt1bKqyggwi9PsXcuuAkQUAAA7
</icon>
<feed-icon>
R0lGODlhEAAQAKIAAAAAADMzM//////qAP/5twAAAAAAAAAAACH5BAAAAAAALAAAAAAQABAAAAM7
GLrcCmDASeEbRFaqMMnbdIGQxgXlhJkWurFtGD5yRdeii8eQMPmCYPAWBBR9PaJxiTQqe0ahwEFl
JAAAOw==
</feed-icon>
</button>
</custombuttons>

タグにはそれぞれ以下のものをいれてます。
<site>~</site>・・・サイトのURL
<title>~</title>・・・サイトのタイトル
<feed>~</feed>・・・RSSフィードのURL
<description>~</description>・・・サイトの概要
<search>~</search>・・・検索を実行するURL(デフォルトはGETでクエリを送信)
<icon>~</icon>・・・ツールバーアイコンをbase64エンコードしたもの
<feed-icon>~</feed-icon>・・・新しいアイテムがある場合に表示される予備のアイコンをbase64エンコードしたもの

アイコンはBMP、ICO、GIF、およびJPEGなどで作成した後、base64でエンコード変換してくれるWEBサイトを利用します。
http://www.motobit.com/util/base64-decoder-encoder.asp

今回は2つの画像をエンコードしました。
 ツールバーアイコン
 予備のツールバーアイコン


XMLを保存してサーバにアップロードします。 あとは以下コードをhtml内に記述すればインストールリンクを作成することができます。
<a href="http://toolbar.google.com/buttons/add?url=URL">Add</a>


実際に↓こちらにリンクを貼ってあります。



無事、登録できると以下のようになります。



最終的には自分のサイトで配布したり、「Google ツールバー ボタン ギャラリー」登録したり、案件でプレゼンしてみてもいいんじゃないでしょうか。
trackbacks(0) comments(0)
外部swfファイルを親ファイルに読み込む場合は、LoadChildまたはLoadChildAtクラスで読み込みます。
同ドメイン上にあるファイルであれば以下のようにして読み込むことができました。

SOURCE:
package myproject.pages.contents{
	import jp.progression.casts.*;
	import jp.progression.commands.*;
	import jp.progression.events.*;
	import jp.progression.loader.*;
	import jp.progression.*;
	import jp.progression.scenes.*;
	
	import flash.display.Sprite;
	import flash.display.MovieClip;
	import flash.display.Loader;
	import flash.net.URLRequest;
	
	import myproject.assets.*;
	
	/*======================================================================*//**
	 * Contents1Page
	 */
	public class Contents1Page extends CastSprite {
		
		private var swfURL:String = "content1.swf";
		private var _container:Sprite = new Sprite();
		private var _loader:MovieClip;
		private var loadData:Loader;
		
		/*======================================================================*//**
		 * コンストラクタ
		 */		
		public function Contents1Page( initObject:Object = null ) {
			
			super( initObject );
			
			_loader = new CtsLoader();
			
		}
		
		protected override function _onCastAdded():void {
			addCommand(
				new LoadChild( _container, new URLRequest( swfURL ), {
					loader: { 
						x:0,
						y:0,
						onCastLoadStart:loadStartHandler,
						onCastLoadComplete:loadCompleteHandler
					}
				} ),
				function ():void {
					loadData = this.latestData;
				}
			);
		}
		
		protected override function _onCastRemoved():void {
			addCommand(
				new UnloadChild( _container, loadData ),
				new RemoveChild(this, _container)
			);
		}
		////////////////////////////////////////////////// ロードスタート
		private function loadStartHandler():void {
			addCommand(
				new AddChild(this, _loader)
			);
		}
		////////////////////////////////////////////////// ロード完了
		private function loadCompleteHandler():void {
			addCommand(
				new RemoveChild(this, _loader),
				new AddChild(this, _container)
			);
		}
	}
}

後で、UnloadできるようにLoadChild直後this.latestDataをloadDataに格納してます。

サンプル | ソース
trackbacks(0) comments(0)

Flashのフレームワーク「Progression」のサンプルを作ってみました。クラスベースで作ってます。
サンプルの流れはイントロ~トップ~コンテンツになってます。

サンプル | ソース


大量にページがあるフラッシュサイト等ではめんどくさ~いページ遷移をProgressionが担当してくれるので、すごく重宝します。
シーン機能があるので、制作はそのシーンだけに集中することができますし、連続するアニメーションもコマンドを使えば視覚的に分かりやすく書くことができます。
と、制作サイドにとってはいろいろメリットがあるのですが、ユーザにとってもディープリンク機能によって直接コンテンツにアクセスできたりします。(←設定すれば)


以下、制作する際の個人的メモ。
・1つのクラスのディレクトリ内に大量にファイルを置かない。(インポートする時しんどくなる)
・libsディレクトリはアップデートすると中身が入れ替わるので、自分のクラスなどは置かない。
・基本的に自分のことは自分でする。(AddChildしたら自分でRemoveChildする、フェードインしたらアウトする)
・シーンイベントの実行タイミングを把握する。
FlashOOPのコチラの「イベント処理の仕様を決める」の項が分かりやすいです。


関連リンク:
Progression.jp
Progression 3.0 - API Reference
Progression examples ...漁ると勉強になります
blog.progression.jp
特集:Flashのフレームワーク「Progression3」を始めてみよう!|gihyo.jp

trackbacks(0) comments(0)
今まで、物体同士は勝手に衝突していたのですが、ある程度コントロールできるようなのでテスト。
テスト用に円と四角を5個づつ作り、円と円、または四角と四角が衝突したら、色を変えてます。円と四角は衝突しません。
まずはプレビューを。

何かと何かが衝突した場合、b2Bodyクラスのm_contactListで取得できますので、以下のように毎フレーム実行。

SOURCE:
for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next) {
	//衝突判別
	for (var ce:b2ContactEdge = bb.m_contactList; ce != null; ce = ce.next) {
	
		if (ce.contact.GetShape1().m_body.m_userData.id != "wall" && ce.contact.GetShape2().m_body.m_userData.id != "wall" && ce.contact.GetManifoldCount() == 1) {
		
			var mc1 = ce.contact.GetShape1().m_body.m_userData;
			var mc2 = ce.contact.GetShape2().m_body.m_userData;
		
			mc1.changeColor();
			mc2.changeColor();
		
		}
	
	}

}
※四方の壁に"wall"というidを設定してます。
GetManifoldCount()はヒットエリアを矩形か?(0)オブジェクトの形か?(1)を判断してます。

衝突するオブジェクトをコントロールするには、b2ShapeクラスのcategoryBits、maskBitsを使用します。 Mtok-blogさんの記事を参考にすると、body同士が重なった時に一方のcategoryBitsともう一方のmaskBitsの論理積(AND)が0でなかった場合に衝突するそうです。
壁、円、四角は以下のように設定すると、円と四角の場合は衝突しなくなりました。(ちょっと論理積に自信がありませんが・・・)

SOURCE:
//壁
wallObject.filter.categoryBits = 0x0011;
wallObject.filter.maskBits = 0x0011;
//円
circle.filter.categoryBits = 0x0001;
circle.filter.maskBits = 0x0001;
//四角
rect.filter.categoryBits = 0x0010;
rect.filter.maskBits = 0x0010;
ソース
※ダウンロードしたソースはBox2DとTweenerにパスをつなげてください。


参考にした記事:
Box2Dサンプル maskBitsによる衝突フィルタリング | Mtok-blog
Box2d で降りしきる箱と戯れる箱 | parpue.net

衝突は他にもオブジェクトにid名を付けて、if文で分岐する方法や、
Box2DFlashAS3での衝突判定 | FICC LABS
コンタクトリスナを使って検出する方法などあります。
第7回 円を落として星を飛び散らせる|gihyo.jp

Box2DFlashAS3が2.0.2にバージョンUPした模様ですね。でもマイナーバージョンなんでスルーします。
Box2DFlashAS3 2.0.2 ダウンロードページ


trackbacks(0) comments(0)
キーボードからの入力を受け付ける場合もマウスと同様でInputクラスを使用します。
SOURCE:
import General.Input;

キーボードが押されたかどうかを判断するには以下のように記述すると、Boolean値を返してくれます。

キーを押した時:
Input.isKeyPressed(キーコード)

キーを離した時:
Input.isKeyReleased(キーコード)

isKeyPressed、isKeyReleased共に、アクションが実行された1回のみしか値を返してくれませんので、キーを押しっぱなしかどうかを判断するには以下、isKeyDownを使用します。

キーを押し続けている時:
Input.isKeyDown(キーコード)

← (左矢印)だと「37」、→ (右矢印)だと「39」という感じです。 キーコード一覧に関しては、Adobeのlivedocsで確認できます。キーボードのキーとキーコードの値


以下、オブジェクトを矢印キーで操作する部分です。
SOURCE:
		private function update(event:Event) {
			
			m_world.Step(m_timeStep, m_iterations);
			
			for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next) {
				if (bb.m_userData is Sprite){
					bb.m_userData.x = bb.GetPosition().x * m_physScale;
					bb.m_userData.y = bb.GetPosition().y * m_physScale;
					bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI);
				}
			}
			
			//キーを押した場合
			if (Input.isKeyDown(39)) {
				// Right Arrow
				var pt1:b2Vec2 = new b2Vec2(bar.GetPosition().x + 5 / m_physScale, bar.GetPosition().y);
				bar.WakeUp();
				bar.SetXForm(pt1, 0);
			}
			else if (Input.isKeyDown(37)) {
				// Left Arrow
				var pt2:b2Vec2 = new b2Vec2(bar.GetPosition().x - 5 / m_physScale, bar.GetPosition().y);
				bar.WakeUp();
				bar.SetXForm(pt2, 0);
			}
			
			Input.update();
			
		}

※オブジェクトを動かす際にWakeUp()でsleepモードを解除しないと、壁などを突き抜けてしまいます。
プレビュー | ソース


ワールド内での現在のポジションはGetPosition()で。
GetPosition()コンストラクタ
public function GetPosition() : b2Vec2
b2Body.GetPosition().x、b2Body.GetPosition().yで取得

オブジェクトを移動させる場合はb2XForm()。
b2XForm()コンストラクタ
public function b2XForm(pos:b2Vec2=null, r:b2Mat22=null)

trackbacks(0) comments(0)

2011年3月

    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
twitter