Home > Box2D

Box2D Archive

WCAN mini ActionScript vol.12で使ったスライド


WCANネタは何にしようかなぁ…ブログにアップしてるものを当日なぞるだけだと、味気ないし…

あと、スライドも作らないと…

暫くどうしようかなぁ…と考えていたんですが…

「そうか、(Progression+CMSで)スライドを作れば、両方(の問題を)一気にクリア出来る!」。

Progresssion + CMS + Box2Dでスライド

で、作ってみました。(デバイスフォントに変更してあります)

サムネイルに表示されている数字が、スライド番号と一致しています。(1枚目のスライドを表示させる場合は、1と書かれたサムネイルをクリック)

以前にProgressionとCMSを絡めてPhotoアルバム的なものを作ったんですが、それを触っていたら…

サムネイルをクリック→詳細ページに遷移→サムネイルの一覧ページに戻るという流れって、スライドに応用出来るなと思いまして…

Photoアルバムの時と同様、テンプレートを作成しました。

<?xml version="1.0" encoding="UTF-8" ?>
<prml version="2.0.0" type="text/prml">
<mt:Entries lastn="50" sort_order="ascend">
<scene name="<$mt:EntryBaseName$>" cls="flabaka.scenes.ImageScene" title="<$mt:EntryTitle$>">
<mt:EntryAssets type="image">
<cap><$mt:EntryTitle$></cap>
<contents><$MTEntryMore$></contents>
<path><$mt:AssetURL$></path>
<count><$MTEntryKeywords$></count>
</mt:EntryAssets>
</scene>
</mt:Entries>
</prml>

★気をつける箇所・1

mt:Entriesでsort_order=”ascend”にしているというところでしょうか…

sort_order=”ascend(昇順)”を記述しないと、初期値は”descend”(降順)になってしまいます。

これだとスライドが逆再生してしまうことになるので、sort_order=”ascend”にしてあります。

★気をつける箇所・2

あとPhotoアルバムの時と違う箇所といえば、$MTEntryMore$を使っているくらいでしょうか…

通常の本文を入力する箇所には、サムネイルに貼り付ける画像をアップしています。

本文の箇所に画像をアップロード

なので、あと余っている箇所といえば、「続き」の箇所だったので、そこを使うことにしました。

続きにコードを打ち込む

ここにスライドに表示させる文章を入力します。その際、Flashで扱うことの出来るHTMLタグでマークアップしてあげます。

今回、僕は<li>と<br>タグしか使っていません。

<li>flabakaというブログを書いています。</li><br><li>東京でDTPをやってます。</li><br><li>Flash&ActionScript大好き人間です!</li>

あと、現在スライドの何枚目というものを表示させたいので、キーワードのフィールドを使うことにしました。

一枚目のスライドなら、キーワードに1と入力します。

MTをお使いの方ならば、カスタムフィールドを使ってあげてもいいかと思います(僕が使ったのはMTOSなので…)。

あとは、スライドの枚数分、記事を投稿していくだけです。

Progression側で行った事

  1. スライドとなるSceneObjectを作成
  2. そこにテキストフィールドを作成
  3. テキストフィールドの.htmlTextにXMLのcontentsを渡してあげる
  4. あとはTextFormatにいろいろ設定してあげる

すると、いい感じでスライドになってくれます。

★スライドのカウントの箇所

この表示はどうやっているかというと…

IndexSceneでXMLをパースした際、スライドが何枚あるかを、配列(例えばmy_array)にpushしておきます。

あとは、表示させたい所で配列(my_array)を取得して、「XMLのcount + ” / ” + my_array.length」みたいな感じで(テキストに)渡しています。

作ってみて思ったこと

Flashは一回パブリッシュしておけば、あとは触らずに、XMLファイルを変更するだけでスライドの修正&追加・削除が簡単に行えます。

まぁ、自分一人で作業を全て行っちゃうとか、このくらいのテキスト量なら、わざわざCMSを使わないでエディタでコードを打った方が早いとは思いますが…(ProgressionとCMSの連携を試したかったので、その点はご容赦ください)

WordPressとの連携は、次回のエントリで…

Progression + CMS + Box2D


以前作成したProgression + CMSで作ったPhoto Album的なものに、今度はBox2Dを絡めてみました。

これもブログ記事を投稿すると、上から降ってくるサムネイルが増えていきます。

作成方法はPaperVision3Dを絡めたときと、ほぼ一緒です。

  1. CastSpriteを継承したBox2Dのクラスを作成
  2. 作成したクラスに、Box2Dのworldを作成
  3. 重力とか物理エンジンとかを設定
  4. 床やBoxを作成
  5. BoxのuserDataにサムネイルのインスタンスを貼り付ける

2~4は、普通にBox2Dの設定をしてあげれば問題ありません。

インスタンスの取得方法は、PaperVisionを絡めた時と一緒です。

userDataに取得したインスタンスをそのまま渡してあげると、(多分、僕のソースの書き方が悪いからだと思いますが)パブリッシュの際、エラーになってしまいました。

なので、userDataはとりあえずSpriteにしておいて、そこに(取得した)インスタンスをaddChildしてあげる形を取りました。

そうすると、エラーは出なくなりました。

Spriteでくるんだせいなのかは分かりませんが、サムネイルが斜めになってしまうと、エッジのギザギザが目立ってしまいます。

インスタンスにはsmoothingが適用されていて、そのまま(サムネイルを)addChildする分には、そんなことはないのですが…

ここらあたりは、要検証。

あと画像の読み込みが完了するまで、Boxが落ちてこないという設定もしていないので、(当サンプルでは)落ちながら画像を読み込んでいるって感じになっています。

(Box2Dの空間に配置している)サムネイルにロールオーバーすると、きちんとツールチップが適用されます。

サムネイルをクリックすると、写真の詳しい説明のページに遷移します。

いや~、Progression凄い!

★追記(2009/06/27)

userDataに画像を貼り付けると、こんな感じになりました。

Box2Dの座標軸

Box2Dの原点(0,0)はオブジェクトの中心になっているみたいなので、画像を貼り付ける際には、位置調整が必要になってきます。

Q-films


Q-filmsのホームページ

ClockMakerさんがお作りになったサイト、Q-films

ご本人さまがブログにお書きになられているように、Progression+Box2D+Papervision3Dで作成されているみたいです。

サイトに流れているサウンドやマウスオーバー時の効果音(どちらも自作されたのかな?)も小気味いいし、footerにはFull ScreenやSoundのOn・Offボタンに加え、はてブ、livedoor Clip、Deliciousに追加のボタンも用意されています(とても親切っ)。

ナビゲーションに加え、ブクマに追加のボタンにマウスオーバーすると、(サイトデザインに合わせ)カスタマイズされたToolTipテキストが表示されるし…

カスタマイズされたToolTip

とても素敵なサイトだったので、先行チケットを申し込んじゃいました。

マウスホイールでグリグリはまだ試していないので、後でやってみようっと!

BOX2Dのm_userData


FIVe3Dで作成したオブジェクトを、BOX2Dに配置して落下とかマウスで掴めるように出来ないかなぁ…と思っているんですが、上手くいかない。

FIVe3Dではオブジェクトをマウスで掴める(startDrag)ようにするのは無理っぽいんで、こんなことを考えたんですが…

Papervision3DとBOX2Dの組み合わせで作品(サンプル)を公開されている方が沢山いらっしゃるので、Papervision3DをFIVe3Dに変えたらいいんじゃない? という単純かつ安易な発想です。はい。

BOX2Dのm_userDataはデータ型が「*」だから、何でも突っ込めるよと(いろんな記事&BOX2Dのクラスファイルに)書かれているので、試しにやってみても…

怒られる、怒られる。

BOX2D側で作成したBOXに(自前の)画像を貼るとかは、簡単に出来たんですが…

3D(FIVe3D)で作成したオブジェクトを2D(BOX2D)に配置するのは、無理なんですかねぇ…

画像を適用させてみる


Box2DでActionScript物理プログラミング』(gihyo.jp)の連載第六回目に画像を使って表現力アップの記事が掲載されていたので、それを元に以前に作成したものに画像を適用させてみました(オブジェクトはドラッグ可能です)。

画像を適用させてみたデモ

記述したソースはこんな感じ。

package  {
	import Box2D.Collision.b2AABB;
	import Box2D.Collision.Shapes.b2CircleDef;
	import Box2D.Collision.Shapes.b2PolygonDef;
	import Box2D.Collision.Shapes.b2PolygonShape;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2DebugDraw;
	import Box2D.Dynamics.b2World;
	import Box2D.Dynamics.Joints.b2MouseJoint;
	import Box2D.Dynamics.Joints.b2MouseJointDef;
	import Box2D.Dynamics.Joints.b2RevoluteJoint;
	import Box2D.Dynamics.Joints.b2RevoluteJointDef;
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.display.*;

	//ドラッグ可能なBOX
	 
	public class DragObject extends Sprite {
		
		//Worldを定義
		private var world:b2World;

		// boxBodyの定義
		private var boxBody:b2Body;

		// マウスジョイントの定義
		private var mouseJointDef:b2MouseJointDef;

		// マウスジョイント
		private var mouseJoint:b2MouseJoint;
		
		//画像の設定(BOX)
		[Embed(source='box.jpg')]
		private var BoxImage:Class;
		
		//画像の設定(floor)
		[Embed(source='floor.jpg')]
		private var FloorImage:Class;
				
		//コンストラクタ
		public function DragObject():void {
				
			//ステージの設定
			stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

			////////////////////////////////////////
			// 物理エンジンのセットアップ
			////////////////////////////////////////
			
			// 外枠を定義する
			var worldAABB:b2AABB = new b2AABB();
			worldAABB.lowerBound.Set(-100, -100);
			worldAABB.upperBound.Set(100, 100);
			
			// 重力を下方向に10m/s^2とする
			var gravity:b2Vec2 = new b2Vec2(0, 10);
			
			// 外枠と重力を指定して、物理エンジン全体をセットアップする
			world = new b2World(worldAABB, gravity, true);
			
			////////////////////////////////////////
			// 壁の設定
			////////////////////////////////////////
			
			// 天井の位置を左から2.5m、上から3.65mに設置
			var topBodyDef:b2BodyDef = new b2BodyDef();
			topBodyDef.position.Set(2.5, 3.65);
			topBodyDef.angle = 0;
			
			// 天井の形を、幅5m、厚さ20cmとする(指定値は半分の値)
			var topShapeDef:b2PolygonDef = new b2PolygonDef();
			topShapeDef.SetAsBox(2.5, 0.1);
			topShapeDef.density = 20.0;
			topShapeDef.restitution = 0.5;
			topShapeDef.friction = 0.2;
			
			var topfloor:b2Body = world.CreateStaticBody(topBodyDef);
			topfloor.CreateShape(topShapeDef);
			
			// 天井の画像を読み込んで表示する
			var topfloorImage:Bitmap = new FloorImage()
			topfloorImage.width = 5 * 100;
			topfloorImage.height = 0.2 * 100;
			topfloorImage.x = - topfloorImage.width / 2;
			topfloorImage.y = - topfloorImage.height / 2;
			topfloor.m_userData = new Sprite();
			topfloor.GetUserData().x = topfloor.GetWorldCenter().x * 100;
			topfloor.GetUserData().y = topfloor.GetWorldCenter().y * 100;
			topfloor.GetUserData().addChild(topfloorImage);
			addChild(topfloor.GetUserData());
			
			// 床の位置を左から2.5m、上から0.1mとする
			var buttomBodyDef:b2BodyDef = new b2BodyDef();
			buttomBodyDef.position.Set(2.5, 0.1);
			buttomBodyDef.angle = 0;
			
			// 床の形を、幅5m、厚さ20cmとする(指定値は半分の値)
			var buttomShapeDef:b2PolygonDef = new b2PolygonDef();
			buttomShapeDef.SetAsBox(3.35, 0.1);
			buttomShapeDef.density = 20.0;
			buttomShapeDef.restitution = 0.5;
			buttomShapeDef.friction = 0.2;
			
			var buttomfloor:b2Body = world.CreateStaticBody(buttomBodyDef);
			buttomfloor.CreateShape(buttomShapeDef);
			
			// 床の画像を読み込んで表示する
			var buttomfloorImage:Bitmap = new FloorImage()
			buttomfloorImage.width = 5 * 100;
			buttomfloorImage.height = 0.2 * 100;
			buttomfloorImage.x = - buttomfloorImage.width / 2;
			buttomfloorImage.y = - buttomfloorImage.height / 2;
			buttomfloor.m_userData = new Sprite();
			buttomfloor.GetUserData().x = buttomfloor.GetWorldCenter().x * 100;
			buttomfloor.GetUserData().y = buttomfloor.GetWorldCenter().y * 100;
			buttomfloor.GetUserData().addChild(buttomfloorImage);
			addChild(buttomfloor.GetUserData());
			
			// 左の壁の位置を左から0.1m、上から1.25mとする
			var leftBodyDef:b2BodyDef = new b2BodyDef();
			leftBodyDef.position.Set(0.1, 1.25);
			leftBodyDef.angle = 90 * Math.PI / 180;
			
			// 壁の形を、幅5m、厚さ20cmとする(指定値は半分の値)
			var leftShapeDef:b2PolygonDef = new b2PolygonDef();
			leftShapeDef.SetAsBox(2.5, 0.1);
			leftShapeDef.density = 20.0;
			leftShapeDef.restitution = 0.5;
			leftShapeDef.friction = 0.2;
			
			var leftfloor:b2Body = world.CreateStaticBody(leftBodyDef);
			leftfloor.CreateShape(leftShapeDef);
			
			// 床の画像を読み込んで表示する
			var leftfloorImage:Bitmap = new FloorImage()
			leftfloorImage.width = 5 * 100;
			leftfloorImage.height = 0.2 * 100;
			leftfloorImage.x = - leftfloorImage.width / 2;
			leftfloorImage.y = - leftfloorImage.height / 2;
			leftfloor.m_userData = new Sprite();
			leftfloor.GetUserData().x = leftfloor.GetWorldCenter().x * 100;
			leftfloor.GetUserData().y = leftfloor.GetWorldCenter().y * 100;
			leftfloor.GetUserData().rotation = 90;
			leftfloor.GetUserData().addChild(leftfloorImage);
			addChild(leftfloor.GetUserData());
			
			
			
			// 右の壁の位置を左から4.9m、上から1.25mとする
			var rightBodyDef:b2BodyDef = new b2BodyDef();
			rightBodyDef.position.Set(4.9, 1.25);
			rightBodyDef.angle = 90 * Math.PI / 180;
			
			// 床の形を、幅5m、厚さ20cmとする(指定値は半分の値)
			var rightShapeDef:b2PolygonDef = new b2PolygonDef();
			rightShapeDef.SetAsBox(2.5, 0.1);
			rightShapeDef.density = 20.0;
			rightShapeDef.restitution = 0.5;
			rightShapeDef.friction = 0.2;
			
			var rightfloor:b2Body = world.CreateStaticBody(rightBodyDef);
			rightfloor.CreateShape(rightShapeDef);
			
			// 床の画像を読み込んで表示する
			var rightfloorImage:Bitmap = new FloorImage()
			rightfloorImage.width = 5 * 100;
			rightfloorImage.height = 0.2 * 100;
			rightfloorImage.x = - rightfloorImage.width / 2;
			rightfloorImage.y = - rightfloorImage.height / 2;
			rightfloor.m_userData = new Sprite();
			rightfloor.GetUserData().x = rightfloor.GetWorldCenter().x * 100;
			rightfloor.GetUserData().y = rightfloor.GetWorldCenter().y * 100;
			rightfloor.GetUserData().rotation = 90;
			rightfloor.GetUserData().addChild(rightfloorImage);
			addChild(rightfloor.GetUserData());
			
			////////////////////////////////////////
			// 箱の設置
			////////////////////////////////////////
			
			// 箱を発生させる
			var boxBodyDef:b2BodyDef = new b2BodyDef();
			boxBodyDef.position.Set(1.5, 1);
			
			// 箱の形を、幅50cm、高さ50cmとして45度ぐらい右に回す
			var boxShapeDef:b2PolygonDef= new b2PolygonDef();
			boxShapeDef.SetAsOrientedBox(0.25, 0.25, new b2Vec2(0, 0), 0.8);
			boxShapeDef.density = 1;
			boxShapeDef.restitution = 0.35; 
			
			// BOXを作る
			
			boxBody = world.CreateDynamicBody(boxBodyDef);
			boxBody.CreateShape(boxShapeDef);
			boxBody.SetMassFromShapes();
			
			// BOXの画像を読み込んで表示する
			var boxImage:Bitmap = new BoxImage()
			boxImage.width = 0.5 * 100;
			boxImage.height = 0.5 * 100;
			boxImage.x = - boxImage.width / 2;
			boxImage.y = - boxImage.height / 2;
			boxBody.m_userData = new Sprite();
			boxBody.GetUserData().x = boxBody.GetWorldCenter().x * 100;
			boxBody.GetUserData().y = boxBody.GetWorldCenter().y * 100;
			boxBody.GetUserData().addChild(boxImage);
			addChild(boxBody.GetUserData());
			
			
			// マウスジョイントを定義する
			mouseJointDef = new b2MouseJointDef();
			// 片方のbodyにはワールド全体を設定する
			mouseJointDef.body1 = world.GetGroundBody();
			// もう片方には移動させたい物体を設定する
			mouseJointDef.body2 = boxBody;
			// 車体の中心座標を設定する
			mouseJointDef.target = boxBody.GetWorldCenter();
			// マウスで引っ張られるときの力
			mouseJointDef.maxForce = 10;
			// シミュレーションの間隔
			mouseJointDef.timeStep = 1 / 24;
			
			boxBody.WakeUp();
			
			// イベントハンドラを登録する
			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
		}
		
		private function mouseDownHandler(event:MouseEvent):void {
			// マウスボタンが押されたら,マウスジョイントを作る
			mouseJoint = b2MouseJoint(world.CreateJoint(mouseJointDef));
		}
		
		private function mouseUpHandler(event:MouseEvent):void {
			// マウスボタンが離されたら,マウスボタンを切り離す
			world.DestroyJoint(mouseJoint);
			mouseJoint = null;
		}
		
		private function mouseMoveHandler(event:MouseEvent):void {
			// mouseJointがnullでないときだけ処理を実行する
			if (mouseJoint) {
				// マウスが押された場所を物理エンジン内の座標系に変換する
				var x:Number = event.stageX / 100;
				var y:Number = event.stageY / 100;
				// マウスジョイントのカーソル位置を更新
				mouseJoint.SetTarget(new b2Vec2(x, y));
			}
		}
		
		private function enterFrameHandler(event:Event):void {
			for (var b:b2Body = world.GetBodyList(); b; b = b.GetNext()){
				if (b.GetUserData() is Sprite){
					b.GetUserData().x = b.GetWorldCenter().x * 100;
					b.GetUserData().y = b.GetWorldCenter().y * 100;
				}
			}
			// 物理シミュレーションを1/24秒進める
			world.Step(1 / 24, 10);

		}
	}
}

FlashIDEでコンパイルしようとすると怒られたので、今回はFlashDevelop側でコンパイルしてみました。

確かに画像を使うと、表現力がUPした感じがします。

ホーム > Box2D

Search
Feeds
Meta

flashDevelopスポンサー

Return to page top