SIHOのプログラミングわーくワク

興味の赴くままに勉強してたら、読み書きできる言語は9個になりました。他にもいくつか気になる言語があったりなかったり?  まだまだ続く、楽しいお仕事わーくワク♪

  • « 
  • 10 
  • 11 
  • 12 
  • 13 
  • 14 
  • 15 
  • 16 
  • 17 
  • 18 
  • 19 
  • 20 
  • 21 
  • 22 
  • 23 
  • 24 
  • 25 
  • 26 
  • 27 
  • 28 
  • 29 
  • 30 
  • 31 
  • »

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

QuickBox2Dを使ったメニュー表現

2010.03.23 (Tue)

■全体イメージ
QuickBox2Dサンプル

Flashサンプル(別windowでみてね)

少し前にQuickBox2Dを使ってKIOSK(展示向けのモニターに全画面で投影するやつ)コンテンツを作りました。
(※表示されている文字は、「じゅげむじゅげむ」の口上をてきとーにいれているので意味はありません)

QuickBox2Dで扱うオブジェクトのスキンにMCを使うことと、そのMcの中のダイナミックテキストに外部XMLから読み込んだテキストのデータを表示することが自分的に難しかったところです。

実際に某博物館の展示コンテンツに使用しているのでFlashの画面サイズが大きいです。ごめんなさい。

flashは他のシーンと組み合わせるのに都合の良いようにQuickBox2Dの部分だけ別のswfにしておおもとのswfに読み込んで使っています。
なので、コードがちょっと一般的ではないところもあります。
そのため、サンプルファイル一式の掲載ではなく、参考となるコードをまるっと掲載しておきます。
ポイントなどは、後日に隙をみて補足していければよいかなっと。


#あと、だれか、コードを見やすく掲載する良いツールがあったら教えてください。

package
{
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2Body;
import com.actionsnippet.qbox.*;
import flash.display.MovieClip;
import flash.text.*;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.net.*;
import flash.utils.*;
import flash.geom.*;
import flash.system.*;

/**
* @author SIHO
*/
[SWF(width=910, height=884,frameRate=30)]
public class Main extends MovieClip
{
private var mapClor:MovieClip = new Map();
private var _qbox:QuickBox2D;
private var _fixedPoint:b2Vec2 = new b2Vec2(7.75, 7.75);
private var _objDataArray:Array ;
private var objArray:Array = [];
public var mapNo:uint = 1;
public var tf:TextFormat = new TextFormat();
public var hiraginoMaruGo:FontLoader;
public var mainMc:MovieClip;
private var myLoader:URLLoader = new URLLoader();
private const centerPointX:Array = [600, 585,430,270,390,420]//ここ中心点の設定。ピクセルで指定。
private const centerPointY:Array = [370, 550, 590, 580, 280, 430]//ここ中心点の設定
private const offsetX:Number = 364.5;
private const offsetY:Number = 115;
private var myXml:XMLList;
private var st1XML:XMLList;
private var mcArray:Array = [];
private var pointObjArray:Array = [];
private var qboxObjArray:Array = [];
private var anchorArray:Array = [];
private var jointArray:Array = [];
private var timerObj1:Timer;

public function Main():void
{
super();
hiraginoMaruGo = new FontLoader("commons/font.swf", "ShinGoProMedium", this, this);
}
//XMLの呼び出し。
private function archiveXMLLoad():void {
myLoader.addEventListener(Event.COMPLETE, xLoaded);
myLoader.load(new URLRequest("xml/getIsekiList.xml"));
}
//XMLの読み込み完了
private function xLoaded(event:Event):void {
myXml = new XMLList(event.target.data);
build2D();
if (mapNo != 6) createMc();
else createAllMc();
}
//物理エンジン内のobjectを配置する。<<すべて表示するとき
public function createAllMc():void {
mapClor.gotoAndStop("map" + mapNo );

_fixedPoint = new b2Vec2(centerPointX[mapNo - 1] / 30, centerPointY[mapNo - 1] / 30);
st1XML = myXml.isclass;
var cnt:Number = 0;
for (var a:uint=0 ; a < st1XML.length() ; a++) {
var name_str:String = "IsekiPopUp"+String(a+1);
var myClass:Class = Class(getDefinitionByName(name_str));

for (var i:uint = 0 ; i < st1XML[a].iseki.length() ; i++ ) {
//インスタンス作成
mcArray[cnt] = new myClass();
mcArray[cnt].gotoAndStop(46);
//テキスト設定
mcArray[cnt].mcTxt.isekiname.defaultTextFormat = tf
mcArray[cnt].mcTxt.isekikana.defaultTextFormat = tf
var kana_str:String = st1XML[a].iseki[i].@isekiyomi.toString()
var place_str:String = st1XML[a].iseki[i].@isekiname.toString();
mcArray[cnt].mcTxt.isekikana.text = kana_str;
mcArray[cnt].mcTxt.isekiname.text = place_str;

//jointを設定
//アンカー
//anchorArray[cnt] = _qbox.addCircle( {fillAlpha:0, x:(uint(st1XML[a].iseki[i].@isekiX)-offsetX) / 30,y:(uint(st1XML[a].iseki[i].@isekiY)-offsetY) / 30, radius:1/30, density:0} )

//配置設定
mcArray[cnt].x = uint(st1XML[a].iseki[i].@allX) - offsetX
mcArray[cnt].y = uint(st1XML[a].iseki[i].@allY)-offsetY
mcArray[cnt].name = String(st1XML[a].iseki[i].@isno + "_" + st1XML[a].iseki[i].@tyousa)
mcArray[cnt].buttonMode = true;
addChild(mcArray[cnt]);

//qboxObjArray[cnt] = _qbox.addCircle( { density:0, x:(uint(st1XML[a].iseki[i].@allX) - offsetX) / 30 , y:(uint(st1XML[a].iseki[i].@allY) - offsetY ) / 30 , skin:mcArray[i] } );//

//joint
//jointArray[cnt] = _qbox.addJoint( { lineAlpha:1, a:QuickObject(anchorArray[cnt]).body , b:QuickObject(qboxObjArray[cnt]).body,x1:(uint(st1XML[a].iseki[i].@isekiX) - offsetX) / 30, y1: (uint(st1XML[a].iseki[i].@isekiY) - offsetY) / 30, x2: (uint(st1XML[a].iseki[i].@allX) - offsetX) / 30, y2:(uint(st1XML[a].iseki[i].@allY) - offsetY ) / 30} )

mcArray[cnt].addEventListener("click", mClick);
cnt = cnt + 1
}
}
allMCAnime();
}
//[すべてのエリア]の時のアニメーション設定
private function allMCAnime():void{

var timeCount:uint = st1XML.iseki.length();

timerObj1 = new Timer(800, timeCount-1);
timerObj1.addEventListener(TimerEvent.TIMER , onTimer);
timerObj1.addEventListener(TimerEvent.TIMER_COMPLETE, timerComplete);
timerObj1.start();

//順番におおきくなーる。
function onTimer(event:TimerEvent):void {
var i:uint = timerObj1.currentCount ;
var mcIndex:uint = numChildren;
setChildIndex(mcArray[i - 1], mcIndex-1);
mcArray[i-1].gotoAndPlay(15);
}
//すべてのオブジェクト表示が完了して、一息ついたら、繰り返す。
function timerComplete(event:TimerEvent):void {
mcArray[78].gotoAndPlay(15);
var timerObj2:Timer = new Timer(800, 1);
timerObj2.addEventListener(TimerEvent.TIMER_COMPLETE, repeat);
timerObj2.start();
function repeat(event:TimerEvent):void {
allMCAnime();
}
}
}
//物理エンジン内のobjectを配置する。タイミング管理<<エリアごと
public function createMc():void {
mapClor.gotoAndStop("map" + mapNo );
//中心点の調整
//中心点確認用
/*var point:MovieClip = new IsekiPoint();
point.x = centerPointX[mapNo - 1]
point.y = centerPointY[mapNo - 1]
addChild(point)*/
_fixedPoint = new b2Vec2((centerPointX[mapNo - 1] )/ 30, (centerPointY[mapNo - 1] )/ 30);
st1XML = myXml.isclass;

//最初のオブジェクトを作成する
setObj(0);

var timeCount:uint = st1XML[mapNo - 1].iseki.length();
var duration:uint = 1000;
if (mapNo == 3 || mapNo == 4) duration = 300;

if (timeCount) {
timerObj1 = new Timer(duration, timeCount-1);
timerObj1.addEventListener(TimerEvent.TIMER , onTimer);
//timerObj1.addEventListener(TimerEvent.TIMER_COMPLETE, timerComplete);
timerObj1.start();
}else {
timeCount = 0;
}

function onTimer(event:TimerEvent):void {
var i:uint = timerObj1.currentCount ;
setObj(i);
}
//すべてのオブジェクト表示が完了して、一息ついたら、繰り返す。
/*function timerComplete(event:TimerEvent):void {
var timerObj2:Timer = new Timer(10000, 1);
timerObj2.addEventListener(TimerEvent.TIMER_COMPLETE, repeat);
timerObj2.start();
function repeat(event:TimerEvent):void {
removeObj();
}
}*/
}
//エリアごとの表示の時のオブジェクト生成
private function setObj(c:uint):void {
var i:uint = c;
//クラス名設定
var name_str:String = "IsekiPopUp"+mapNo;
var myClass:Class = Class(getDefinitionByName(name_str));
//インスタンス作成
mcArray[i] = new myClass();
//テキスト設定
mcArray[i].mcTxt.isekiname.defaultTextFormat = tf
mcArray[i].mcTxt.isekikana.defaultTextFormat = tf
var kana_str:String = st1XML[mapNo-1].iseki[i].@isekiyomi.toString()
var place_str:String = st1XML[mapNo-1].iseki[i].@isekiname.toString();
mcArray[i].mcTxt.isekikana.text = kana_str;
mcArray[i].mcTxt.isekiname.text = place_str;

//jointを設定
//アンカー
anchorArray[i] = _qbox.addCircle( { x:uint(st1XML[mapNo-1].iseki[i].@isekiX)/30-offsetX / 30,y:uint(st1XML[mapNo-1].iseki[i].@isekiY)/30-offsetY / 30, radius:4/30, density:0} )
var scale:Number = 1.5;
if (mapNo == 3 || mapNo == 4) scale = 1.2;
else if (mapNo == 2) scale = 1.7;

//配置設定
mcArray[i].x = uint(st1XML[mapNo - 1].iseki[i].@isekiX) - offsetX
mcArray[i].y = uint(st1XML[mapNo - 1].iseki[i].@isekiY) - offsetY
mcArray[i].scaleX = scale;
mcArray[i].scaleY = scale;
mcArray[i].name = String(st1XML[mapNo - 1].iseki[i].@isno + "_" + st1XML[mapNo - 1].iseki[i].@tyousa)
mcArray[i].buttonMode = true;
addChild(mcArray[i]);
if (mapNo == 3 || mapNo == 4) mcArray[i].gotoAndPlay(15);

qboxObjArray[i] = _qbox.addCircle({restitution:1.164,fixedRotation:true,density:10,radius: 47*(scale-0.05) / 30,x:uint(st1XML[mapNo-1].iseki[i].@isekiX)/30-offsetX / 30,y:uint(st1XML[mapNo-1].iseki[i].@isekiY)/30-offsetY / 30,skin:mcArray[i]})
mcArray[i].addEventListener("click", mClick);

//joint
jointArray[i] = _qbox.addJoint( { lineAlpha:1,a:QuickObject(anchorArray[i]).body , b:QuickObject(qboxObjArray[i]).body , frequencyHz:0.065,dampingRatio:0.01,length:9.8 } )
//anchorArray[i] = qboxObjArray[i]

//Jointパラメータ
/* x1:Aとジョイントの接続点のx座標,
y1:Aとジョイントの接続点のy座標,
x2:Bとジョイントの接続点のx座標,
y2:Bとジョイントの接続点のy座標,
length:ジョイントの長さ,
frequencyHz:ジョイントの柔らかさ,0に近い数値ほどよく伸びるジョイント
dampingRatio:弾性。0に近い数値ほど伸びた状態から元の長さに戻る力が強まり、大きな数値ほど元の長さへ戻ろうとしなくなる。
collideConnected:AとBの間に衝突判定を持たせる場合はtrue、そうでない場合はfalse*/

//QuickObjectパラメータ
/*density:1 密度
friction:0.5 摩擦係数
restitution:0.2 反発係数
angle: 0
linearDamping:0
angularDamping:0
isBullet:false,
fixedRotation:false
allowSleep: true
isSleeping:false*/
}
//QuickBox2Dの世界を作る
private function build2D():void {
_qbox = new QuickBox2D(this, { gravityY:0 } );
_qbox.setDefault( { radius:45 / 30, lineColor:0xff4747, fillColor:0xff4747,lineAlpha:0} );
//_qbox.createStageWalls({ lineAlpha:0,fillAlpha:0, });
//壁を作る
_qbox.addBox({x:0,y:0,width:910,height:1/30,density:0,fillAlpha:0})
_qbox.addBox({x:0,y:884.5/30,width:910,height:1/30,density:0,fillAlpha:0})
_qbox.addBox({x:0,y:0,width:1/30,height:884.5,density:0,fillAlpha:0})
_qbox.addBox({x:890/30,y:0,width:1/30,height:884.5,density:0,fillAlpha:0})
_qbox.start();
this.addEventListener(Event.ENTER_FRAME, loop);
addMap();
}
//地図の色分けをbase.swfのレイヤーに追加する
private function addMap():void {
if ( Capabilities.playerType == "External") {
mapClor.x = 403.05
mapClor.y = 433.00
addChildAt(mapClor,0)
}else {
//map.swfの読み込み位置を付加する→myForm.x = 364.5;,myForm.y = 115;
mapClor.x = 403.05+364.5
mapClor.y = 433.00 + 115
mainMc.addChildAt(mapClor,1)
}
}
//削除して表示しなおす。
private function removeObj():void
{
if (timerObj1.running) timerObj1.reset();
for (var ic:uint=0 ; ic < jointArray.length ; ic++ ) {
jointArray[ic].destroy();
}
/*for (var i:uint=0 ; i < pointObjArray.length ; i++ ) {
removeChild(pointObjArray[i]);
}*/
for (var ia:uint=0 ; ia < mcArray.length ; ia++ ) {
removeChild(mcArray[ia]);
}
for (var id:uint=0 ; id < anchorArray.length ; id++ ) {
anchorArray[id].destroy();
}
for (var ib:uint=0 ; ib < qboxObjArray.length ; ib++ ) {
qboxObjArray[ib].destroy();
}

//pointObjArray = null;
//pointObjArray = [];
mcArray = null;
mcArray = [];
anchorArray = null;
anchorArray = [];
qboxObjArray = null;
qboxObjArray = [];
jointArray = null;
jointArray = [];
if (mapNo != 6) createMc();
else createAllMc();
}
//地点をクリックされたときのハンドラー
public function mClick(e:*):void {
e.currentTarget.gotoAndStop("clickFr")
//読み込み側(サンプルの場合、base.swf)のswfにclickName:String を用意しておく。
mainMc.clickName = e.currentTarget.name;
}
//背景地図の切り替え
public function gotoMapImg(xbtnNo:uint):void {
mapNo = xbtnNo;
removeObj()
}

//Box2Dのレンダリング
private function loop(e:Event):void
{
//ここ重要----------------------------------------
for (var body:b2Body = _qbox.w.m_bodyList; body ; body = body.GetNext())
{
if (body.IsSleeping())continue;

var f:b2Vec2 = _fixedPoint.Copy();
f.Subtract(body.GetPosition());
f.Normalize();
f.Multiply(1);
f = f.Negative();
body.ApplyForce(f, body.GetWorldCenter());
}
//----------------------------------------
}
//fontが読み込まれたときの処理
public function fontLoaded(fontname:String):void {
tf.font = fontname;
archiveXMLLoad();
}

}

}

コメント

コメントの投稿

トラックバック

この記事のトラックバックURL

 | HOME | 

プロフィール

siho_prof

SIHO
しほ

Twitter:
SIHO_o

viva mambo, inc.
iPhone&iPad / Flash / Kinect
使用言語:Objective-C, ActionScript 3.0, Javascript, Lua, PHP, C#, C, C++, WSH。
F-site staff

Solar System Simulator 広報

Web,スマートフォン、Desktopを問わず、アプリ制作が好物。執筆は必要に応じて。お仕事くださいまし。

サイネージ:ガンダムフロント東京・キャラクターフォトスポット設計(2012/4~常設)

アトラクション:富士急ハイランド 戦国BASARA ゲーム設計&プログラミング(2010/7-2012/4にて常設展示)

イントラシステム:「某メーカー研究所KJ法システム」DB,Flash,PHPを含むソリューション設計&DB構築、「美術系専門学校の生徒管理システム」iPadクライアントを含むソリューション設計&DB構築

iPhone/iPadアプリ:某球団試合速報アプリ、『魂を熱くさせる 宇宙飛行士100の言葉』『Mitaka Gallery -てのひら宇宙-』

書籍同梱ソフト:『4次元デジタル宇宙紀行Mitaka』『DVD-ROM&図解 動く! 深海生物図鑑』『DVD-ROM&図解 ハッブル望遠鏡で見る宇宙の驚異』

著書:『世界一わかりやすい Windows 7』『世界一わかりやすい Flash CS3』

検索フォーム

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。