Flash版 Processing なライブラリ Frocessing を使ってみる

かっこいいアートっぽい描画ができるプログラム環境Processingを、それっぽくFlashのAS3で使えるようにしたライブラリが、Frocessingです。
gihyo.jpの記事(特集:FrocessingではじめるActionScriptドローイング|gihyo.jp … 技術評論社)のサンプルコードを改造しつつ、試しにいろいろ作ってみました。(ライブラリは ver 0.5.7 を使用してます)

サンプル1

白いくねくねした草がランダムに発生してのびていきます。画面クリックで描画をリセットします。


Flash Study 白い草

Actionscript:
  1. package 
  2. {
  3.     import flash.geom.Point;
  4.     import frocessing.display.*;
  5.    
  6.     /**
  7.      * Frocessingのサンプル1
  8.      * くねくね線とランダムな円
  9.      * マウスクリックでリセット
  10.      */
  11.     public class FrocessingSample01 extends F5MovieClip2DBmp
  12.     {
  13.         //描画サイズ
  14.         private var m_stage_width:Number  = 500;
  15.         private var m_stage_height:Number = 500;
  16.        
  17.         //図形描画の座標
  18.         private var m_points/*Point*/:Array//座標を入れる
  19.        
  20.         private var m_point_current_index:int = 0//何番目の座標まで描画するか
  21.            
  22.         public function FrocessingSample01(){
  23.             super();
  24.         }
  25.        
  26.         //初期化 Stage が呼び込まれたときに自動的に呼ばれる
  27.         public function setup():void {
  28.            
  29.             //描画範囲指定
  30.             size( m_stage_width, m_stage_height );
  31.            
  32.             //背景色指定(引数の数によって色の指定方法が変わる)
  33.             background(0, 1)// color, alpha
  34.            
  35.             //座標セット
  36.             setPoints();
  37.         }
  38.        
  39.        
  40.         //図形描画の座標をセット
  41.         private function setPoints():void {
  42.            
  43.             m_points = new Array();
  44.    
  45.             var len:int = m_stage_width - random(m_stage_height / 2);
  46.             var point_num:int = len / 10;
  47.            
  48.             var step:int = len / point_num + random(5, 1);
  49.             var start_x:Number = Math.random() * m_stage_width; //y軸スタート位置はランダム
  50.            
  51.             var yure:Number = random(6, 2)//くねくねサイズ
  52.            
  53.             var pt:Point;
  54.            
  55.             for (var i:int = 0; i <point_num ; i++) {
  56.                 pt = new Point(start_x + random(yure, -yure), -step * i );
  57.                 m_points.push(pt);
  58.             }
  59.            
  60.             //始点と終点は同じ値を2つ入れる(始点と終点はコントロールポイントになってるっぽいので)
  61.             pt = m_points[0].clone();
  62.             m_points.unshift(pt);
  63.            
  64.             pt = m_points[m_points.length - 1].clone();
  65.             m_points.push(pt);
  66.         }
  67.        
  68.        
  69.         //描画(フレーム毎に繰り返し)
  70.         public function draw():void {
  71.            
  72.             //マウスが押された場合
  73.             if ( isMousePressed ) {
  74.                 //背景を塗りなおす(描画のリセット)
  75.                 background(0, 1);
  76.             }
  77.            
  78.             //原点の移動
  79.             translate( 0, m_stage_height);
  80.            
  81.             //-----くねくね線-----
  82.            
  83.             //塗りをなしに
  84.             noFill();
  85.            
  86.             //線色の指定(引数の数によって色の指定方法が変わる)
  87.             stroke(255, 255, 255, 0.5)//R, G, B, alpha
  88.            
  89.             //線幅指定
  90.             strokeWeight(0.1);
  91.            
  92.             var pt:Point;
  93.            
  94.             //頂点を複数持つ図形の描画
  95.             beginShape();
  96.             for (var i:int = 0; i <m_point_current_index ; i++) {
  97.                 pt = m_points[i];
  98.                 curveVertex(pt.x, pt.y);
  99.             }
  100.             endShape();
  101.            
  102.            
  103.             //-----ランダムな円-----
  104.            
  105.             //線をなしに
  106.             //noStroke();
  107.            
  108.             strokeWeight(1);
  109.            
  110.             //塗り設定
  111.             fill(255, 255, 255, 0.5);
  112.            
  113.             if(m_point_current_index> 0){
  114.                 pt = m_points[m_point_current_index - 1];
  115.             }
  116.             else {
  117.                 pt = m_points[0];
  118.             }
  119.             //円の描画
  120.             var maru_size:Number = random(15, 1);
  121.             ellipse(pt.x + random(15, -15), pt.y + random(10, -10), maru_size, maru_size);
  122.            
  123.             //描画する座標進める
  124.             m_point_current_index++;
  125.            
  126.             //最後の座標まで行ったら座標再設定
  127.             if (m_point_current_index> m_points.length) {
  128.                 m_point_current_index = 0;
  129.                 setPoints();
  130.             }
  131.         }
  132.     }
  133. }

サンプル2

画面クリック位置に種をおいて、カラフルなくねくねした草が伸びていきます。右上の□四角をクリックすると、描画をリセットします。


Flash Study 色の種草

Actionscript:
  1. package 
  2. {
  3.     import flash.geom.Point;
  4.     import frocessing.display.*;
  5.    
  6.     /**
  7.      * Frocessingのサンプル2
  8.      * くねくね線と直線の枝と枝先にランダムな円
  9.      * マウスクリック位置で生える
  10.      * 背景は透過にしてみた
  11.      */
  12.     public class FrocessingSample02 extends F5MovieClip2DBmp
  13.     {
  14.         //描画サイズ
  15.         private var m_stage_width:Number  = 500;
  16.         private var m_stage_height:Number = 500;
  17.        
  18.         //図形描画の座標
  19.         private var m_points/*Point*/:Array//座標を入れる
  20.        
  21.         private var m_point_current_index:int = 0//何番目の座標まで描画するか
  22.        
  23.         //線と塗りの色
  24.         private var m_color:uint;
  25.            
  26.         public function FrocessingSample02(){
  27.             super();
  28.         }
  29.        
  30.         //初期化 Stage が呼び込まれたときに自動的に呼ばれる
  31.         public function setup():void {
  32.            
  33.             //描画範囲指定
  34.             size( m_stage_width, m_stage_height );
  35.            
  36.             //背景色指定(引数の数によって色の指定方法が変わる)
  37.             background(0, 0)// color, alpha
  38.         }
  39.        
  40.        
  41.         //図形描画の座標をセット
  42.         private function setPoints(base_x:Number, base_y:Number):void {
  43.            
  44.             m_point_current_index = 0;
  45.             m_points = new Array();
  46.            
  47.             var len:int = m_stage_width - random(m_stage_height / 1.5);
  48.             var point_num:int = len / 10;
  49.            
  50.             var step:int = len / point_num + random(5, 1);
  51.            
  52.             var yure:Number = random(5, 1)//くねくねサイズ
  53.            
  54.             var pt:Point;
  55.            
  56.             for (var i:int = 0; i <point_num ; i++) {
  57.                 pt = new Point(random(yure, -yure) + base_x, -step * i + base_y);
  58.                 m_points.push(pt);
  59.             }
  60.            
  61.             //始点と終点は同じ値を2つ入れる(始点と終点はコントロールポイントになってるっぽいので)
  62.             pt = m_points[0].clone();
  63.             m_points.unshift(pt);
  64.            
  65.             pt = m_points[m_points.length - 1].clone();
  66.             m_points.push(pt);
  67.         }
  68.        
  69.         //ランダムな色を設定
  70.         private function setRandomColor():void {
  71.            
  72.             var r:uint = random(200, 50);
  73.             var g:uint = random(200, 50);
  74.             var b:uint = random(200, 50);
  75.            
  76.             m_color = this.color(r, g, b);
  77.         }
  78.        
  79.        
  80.         //描画(フレーム毎に繰り返し)
  81.         public function draw():void {
  82.            
  83.             //マウスが押された場合
  84.             if ( isMousePressed ){
  85.                 //色再設定
  86.                 setRandomColor();
  87.                
  88.                 //座標再設定
  89.                 setPoints(mouseX, mouseY - m_stage_height);
  90.             }
  91.            
  92.             if (m_points != null) {
  93.                
  94.                 var i:int = 0//汎用カウンタ
  95.                 var maru_size:Number = 0//円サイズ
  96.                
  97.                 //原点の移動
  98.                 translate( 0, m_stage_height);
  99.                
  100.                 //-----くねくね線-----
  101.                
  102.                 //塗りをなしに
  103.                 noFill();
  104.                
  105.                 //線色の指定(引数の数によって色の指定方法が変わる)
  106.                 stroke(m_color, 0.5)//color, alpha
  107.                
  108.                 //線幅指定
  109.                 strokeWeight(0.1);
  110.                
  111.                 var pt:Point;
  112.                
  113.                 //頂点を複数持つ図形の描画
  114.                 beginShape();
  115.                 for (i = 0; i <m_point_current_index ; i++) {
  116.                     pt = m_points[i];
  117.                     curveVertex(pt.x, pt.y);
  118.                 }
  119.                 endShape();
  120.                
  121.                 //枝
  122.                 if(m_point_current_index> 0 && m_point_current_index <m_points.length - 1){
  123.                    
  124.                     //枝の先の座標設定
  125.                     if(m_point_current_index> 0){
  126.                         pt = m_points[m_point_current_index - 1];
  127.                     }
  128.                     else {
  129.                         pt = m_points[0];
  130.                     }
  131.                     var eda_inc_x:Number = random(30, 0);
  132.                     if (random(1)> 0.5) {
  133.                         eda_inc_x *= -1;
  134.                     }
  135.                     var eda_inc_y:Number = random( -10, -30);
  136.                    
  137.                     var eda_x:Number = eda_inc_x + pt.x;
  138.                     var eda_y:Number = eda_inc_y + pt.y;
  139.                    
  140.                     //直線
  141.                     line(pt.x, pt.y, eda_x, eda_y);
  142.                    
  143.                     //枝の先のランダムな円いくつか
  144.                     noStroke();
  145.                     fill(m_color, 0.5);
  146.                    
  147.                     for (i = 0; i <5;i++){
  148.                         maru_size = random(10, 1);
  149.                         ellipse(eda_x + random(10, -10), eda_y + random(10, -10), maru_size, maru_size);
  150.                     }
  151.                 }
  152.                
  153.                 //伸び始め位置に円を書く
  154.                 if (m_point_current_index == 0) {
  155.                    
  156.                     noStroke();
  157.                     fill(m_color, 0.5);
  158.                    
  159.                     maru_size = 0;
  160.                     for (i = 1; i <5; i++){
  161.                         maru_size += i * random(5, 2);
  162.                         ellipse(m_points[1].x, m_points[1].y, maru_size, maru_size);
  163.                     }
  164.                 }
  165.  
  166.                 //描画する座標進める
  167.                 m_point_current_index++;
  168.                
  169.                 //最後の座標まで行ったら、次の座標が設定されるまで描画止める
  170.                 if (m_point_current_index> m_points.length) {
  171.                     m_point_current_index = 0;
  172.                     m_points = null;
  173.                 }
  174.            
  175.             }
  176.         }
  177.        
  178.         //描画をリセットする
  179.         public function reset():void {
  180.            
  181.             background(0, 0);
  182.         }
  183.     }
  184. }

サンプル3

白い花がランダムに咲きます。咲いた後は、フィルターをかけてぼかしています。画面クリックで描画をリセットします。


Flash Study 白い花

Actionscript:
  1. package 
  2. {
  3.     import flash.geom.Point;
  4.     import flash.filters.BlurFilter;
  5.    
  6.     import frocessing.display.*;
  7.    
  8.     /**
  9.      * Frocessingのサンプル3
  10.      * ランダムな白い線の花にBlurフィルターをかける
  11.      */
  12.     public class FrocessingSample03 extends F5MovieClip2DBmp
  13.     {
  14.         //描画サイズ
  15.         private var m_stage_width:Number  = 500;
  16.         private var m_stage_height:Number = 500;
  17.        
  18.         //花描画開始位置
  19.         private var m_flower_base:Point;
  20.        
  21.         //花サイズ
  22.         private var m_flower_size:Number;
  23.        
  24.         //花サイズ増分値
  25.         private var m_flower_step:Number;
  26.        
  27.         //花の現在サイズ
  28.         private var m_flower_current_size:Number;
  29.        
  30.         //花弁の数
  31.         private var m_kaben_num:int;       
  32.            
  33.         public function FrocessingSample03(){
  34.             super();
  35.         }
  36.        
  37.        
  38.         //初期化 Stage が呼び込まれたときに自動的に呼ばれる
  39.         public function setup():void {
  40.            
  41.             //描画範囲指定
  42.             size( m_stage_width, m_stage_height );
  43.            
  44.             //背景色指定(引数の数によって色の指定方法が変わる)
  45.             background(0, 1)// color, alpha
  46.            
  47.             setFlower();
  48.         }
  49.        
  50.        
  51.         //描画する花の設定
  52.         public function setFlower():void {
  53.            
  54.             m_flower_base = new Point(random(m_stage_width), random(m_stage_height));
  55.             m_flower_size = random(200, 20);
  56.             m_flower_step = m_flower_size / 10
  57.             m_flower_current_size = m_flower_step;
  58.            
  59.             m_kaben_num = random(8, 3);
  60.         }
  61.        
  62.        
  63.         //描画(フレーム毎に繰り返し)
  64.         public function draw():void {
  65.  
  66.             translate( 0, 0);
  67.  
  68.             //塗りをなしに
  69.             noFill();
  70.            
  71.             //線色の指定(引数の数によって色の指定方法が変わる)
  72.             stroke(0xDDDDDD, 0.5)//color, alpha
  73.            
  74.             //花を描く
  75.            
  76.             var kaben_num:int = m_kaben_num;
  77.             var kaben_angle:Number = radians(360 / kaben_num);
  78.             var kaben_len:int = m_flower_current_size / 2;
  79.            
  80.             var base_x:Number = m_flower_base.x;
  81.             var base_y:Number = m_flower_base.y;
  82.            
  83.             beginShape();
  84.             curveVertex(base_x, base_y);
  85.             for (var i:int = 0; i <kaben_num ; i++) {
  86.                 var x1:Number = cos(kaben_angle * i - kaben_angle / 3) * kaben_len / 2 + base_x;
  87.                 var y1:Number = sin(kaben_angle * i - kaben_angle / 3) * kaben_len / 2 + base_y;               
  88.                 var x2:Number = cos(kaben_angle * i) * kaben_len + base_x;
  89.                 var y2:Number = sin(kaben_angle * i) * kaben_len + base_y;
  90.                 var x3:Number = cos(kaben_angle * i + kaben_angle / 3) * kaben_len / 2 + base_x;
  91.                 var y3:Number = sin(kaben_angle * i + kaben_angle / 3) * kaben_len / 2 + base_y;                       
  92.                 curveVertex(base_x, base_y);
  93.                 curveVertex(x1, y1);
  94.                 curveVertex(x2, y2);
  95.                 curveVertex(x3, y3);
  96.                 curveVertex(base_x, base_y);
  97.             }
  98.             curveVertex(base_x, base_y);
  99.             endShape();
  100.            
  101.             //花のサイズ大きくする
  102.             m_flower_current_size += m_flower_step;
  103.            
  104.             if (m_flower_current_size> m_flower_size) {
  105.                 setFlower();
  106.                
  107.                 //フィルタかける
  108.                 bitmapData.applyFilter(bitmapData, bitmapData.rect, new Point(0, 0), new BlurFilter(2, 2));
  109.             }
  110.         }
  111.        
  112.         //描画のリセット
  113.         public function reset():void {
  114.            
  115.             background(0, 1);
  116.         }
  117.     }
  118. }

サンプル4

白い花の上にカラフルな草が伸びていきます。サンプル3の上にサンプル2 を重ねてるだけです。右上の□四角をクリックすると、描画をリセットします。


Flash Study 白い花と色の種草

Actionscript:
  1. var smp3:FrocessingSample03 = new FrocessingSample03;
  2. this.addChild(smp3);
  3.  
  4. var smp2:FrocessingSample02 = new FrocessingSample02;
  5. this.addChild(smp2);
  6.  
  7. var button:Sprite = new Sprite;
  8. button.graphics.beginFill(0xFFFFFF, 1);
  9. button.graphics.drawRect(5, 5, 20, 20);
  10. button.graphics.endFill();
  11.  
  12. button.alpha = 0.5;
  13. button.buttonMode = true;
  14.  
  15. button.addEventListener(MouseEvent.ROLL_OVER,
  16.                         function(e:Event):void {
  17.                             button.alpha = 1;
  18.                         });
  19.  
  20. button.addEventListener(MouseEvent.ROLL_OUT,
  21.                         function(e:Event):void {
  22.                             button.alpha = 0.7;
  23.                         })
  24.                        
  25. button.addEventListener(MouseEvent.MOUSE_UP,
  26.                         function(e:Event):void {
  27.                             smp2.reset();
  28.                             smp3.reset();
  29.                         });
  30.  
  31. this.addChild(button);

使い方の流れ

※F5MovieClipBitmapクラスしか使ってないので、他のクラスを継承した場合の作り方はわかりません…。

  1. F5MovieClipBitmapを継承したクラス作成。
  2. コンストラクタで親のコンストラクタ呼び出す。(明示的に呼び出さないといけないみたいです)
  3. setupメソッドを作って、その中に初期化処理を書く。
  4. drawメソッドを作って、その中に繰り返しの処理を書く。

描画関連のメソッドがAS3と全然違うので、ちょっと戸惑いました。(Processing使ったことないもので)
AS3の描画方法(graphicsクラスのメソッド)は忘れて使った方が混乱しなくていいかなと思います。

ちょこっとコードを書くだけで、結構かっこよさげな描画ができちゃいます。
特に曲線の描画がすごく楽です。
他のクラスも使っていろいろやってみたいです。

Windows上で動くSMTP・POP3サーバ(DNSの機能もあり)Radish

※バージョンは3.0.0-b038使用(2009年6月現在は、3.3.0-b040が最新のようです)

Radishは、Windows上で使えるSMTPアプリケーションです。SMTPだけでなく、POP3・DNSの機能もあります。
設定が簡単なので、メール送受信テスト用に使用してみました。
ローカル内でのメールの送受信ができるようになるまでの、設定と使用方法のメモです。

Radishのサイトのダウンロードから、バイナリ版を落としてきます。
■Radish ダウンロード

解凍したら、Radish.exeを実行
初回起動時に、adish.exeが置いてあるフォルダに、初期設定用のファイル群が作成されます。
タスクバーにRadishのアイコン(白カブくん)が表示されます。

サーバの設定

タスクバーのRadishのアイコンを右クリック→「Radishを開く」で、Radishのメインウインドウを開きます。

SMTP/POP3サーバの設定

「設定」メニューから、「SMTP/POP3サーバの設定」を開きます。

基本設定

サーバ名:localserver
ドメイン名:example.net
ローカル内だけなので、名前は適当に。
他はデフォルトのままで。

SMTPサーバ

バインドアドレスは127.0.0.1にする(ローカル内のみにする)
他はデフォルトのままで。

※バインドアドレスを入れると、アプリケーションが起動するようになるようです(POP3・DNSも)
 起動したくないアプリケーションのバインドアドレスの欄は空欄にします。

POP3サーバ

バインドアドレスはSMTPと同じく 127.0.0.1 を入れる

パスワードのポリシーは、デフォルトのままだと、大文字小文字数字記号を組み合わせて、8文字以上でないとパスワードを登録できないので、面倒ならチェックをはずしたりして変更。

ユーザの登録

設定メニューから、「ユーザ」を開く
POP3(メール受信)で使用するユーザを登録する。
ここでは、テストとしてtest1というユーザを作成。

メーラー側の設定

メーラは何でもいいので、Radishで作成したPOP3ユーザ用のアカウントの設定をします。

受信(POP3)の設定
メールアドレス:test1@localhost
POP3サーバ:localhost
送信(SMTP)の設定
SMTPサーバ:localhost

※メールのあて先アドレスは、ユーザー名@ドメイン名
○test1@example.net

メールの送受信をする

サーバの設定時と同じく、タスクバーのRadishのアイコンを右クリック→「Radishを開く」で、Radishのメインウインドウを開きます。

左下の「Log」タブを選択すると、メール送受信のログが表示されます。

「Log」タブの隣の「Mail」タブを選択すると、送信中のメールキューと、受信したメールボックスのリストが表示されます。

ここで、メールの送受信の状態を調べます。

※メールキューを消す
なぜかアプリケーション側から消せない...ので、メールキューのファイルを直接消します。
Radish.exeが置いてあるフォルダと同じところに、mqueue フォルダがあります。
mqueueフォルダの下に、キューのファイルがたまっているので、直接このファイルを消します。

サーバの停止と起動

タスクバーのRadishのアイコンを右クリック→「サーバ起動」「サーバ停止」「サーバ再起動」を選択します。
もしくは、Radishのメインウインドの、「ツール」メニューから、「サーバ起動」「サーバ停止」「サーバ再起動」を選択します。

物理エンジンライブラリ Box2DFlashAS3 衝突判定と衝突のグループ・カテゴリ分け

Box2Dの衝突判定と、衝突のグループ・カテゴリ分けをする方法のメモです。

衝突判定

Box2Dでは、衝突が起こった物体同士のリストが作成させるので、そのリストを取得して、衝突判定をします。
衝突の起こった物体同士は、b2Worldクラスのm_contactList(ContactListクラス)にb2Contactオブジェクトとして入れられます。
このm_contactListを、Box2Dの演算時に、順次取り出して、衝突時の処理をします。

衝突のグループ・カテゴリ分け

Box2Dで作った物体は、デフォルトでは全ての物体と衝突するようになっています。
これを、ある物体とは衝突するけどある物体とは衝突しないような、グループ分けをするには、b2ShapeDefクラスのfilter(b2FilterDataクラス)の値を変更します。

衝突のグループ・カテゴリ分けの方法

下記の二種類があって、両方を併用することもできます。

  1. groupIndex を使用する
  2. categoryBit と maskBit を使用する
1.groupIndexを使用する

groupIndexを0以外の値を指定して、グループを作る。値が正負かによって、処理が異なる。

  • の同じ値のグループ内の物体は、maskBit・categoryBitの値が何であれ、必ず衝突する
  • の同じ値のグループ内の物体は、maskBit・categoryBitの値が何であれ、必ず衝突しない

別の値のグループとは、maskBit・categoryBitの値によって、衝突判定が決まる。

2.categoryBit と maskBit を使用する

16進数4桁(2進数16桁)の categoryBit を指定。(0x0001)
maskBitも同じく16進数4桁をつける
categoryBitとmaskBitを論理積(AND)で演算して、0にならない物体同士は衝突。

	Aグループ:
		categoryBit=0x0001(0000 0000 0000 0001)
	Bグループ:
		categoryBit=0x0002(0000 0000 0000 0010)
	Cグループ:
		categoryBit=0x0004(0000 0000 0000 0100)

	各グループ内の物体同士を衝突させる
		A
		maskBit=0x0003(0000 0000 0000 0011)
		B
		maskBit=0x0003(0000 0000 0000 0011)
		C
		maskBit=0x0003(0000 0000 0000 0100)

	各グループ内の物体同士と、AとBグループの物体同士を衝突させる
		AとB
		maskBit=0x0006(0000 0000 0000 0011)
		C
		maskBit=0x0006(0000 0000 0000 0100)

maskBit・categoryBitのみで衝突のグループ分けしたい場合は、groupIndexをデフォルトの0のままにしておく

Body作成後に、m_filterの値を変えた場合は、b2WorldクラスのRefilterメソッドを使って、フィルターを再設定してやる必要があるようです。
変えなくてもフィルター設定反映されたのですが、念のため。

サンプルコード

実行結果(きのこと箱)
きのこと箱

※Box2Dのまとめたクラス(Box2DBase)を作って、基本クラスで使ってます。ソースは物理エンジンライブラリ Box2DFlashAS3(基本)にあります。

マウスジョイントの辺りは、Box2Dの付属コード、TestBedのTest.asのサンプルからほぼコピペです。

Actionscript:
  1. public class StudyB2Contact extends B2Base
  2. {   
  3.    
  4.     public function StudyB2Contact()
  5.     {      
  6.         makeB2Walls();
  7.         makeGroup();
  8.        
  9.         this.addEventListener(Event.ENTER_FRAME, update, false, 0, true);
  10.        
  11.         //マウスジョイント用
  12.         this.addEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown, false, 0, true);
  13.         this.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp, false, 0, true);
  14.     }
  15.    
  16.     //Box2D 上下左右の壁作成
  17.     private function makeB2Walls():void {
  18.        
  19.         //デフォルトの衝突フィルターの値
  20.         //categorybit = 0x0001
  21.         //maskBit = 0xFFFF
  22.         //groupIndex = 0
  23.         this.makeB2BodyBox(620, 10, 300, 5, 0, 0, 0.5, 0.5)//上
  24.         this.makeB2BodyBox(620, 10, 300, 495, 0, 0, 0.5, 0.5)//下
  25.         this.makeB2BodyBox(10, 520, 5, 250, 0, 0, 0.5, 0.5)//左
  26.         this.makeB2BodyBox(10, 520, 595, 250, 0, 0, 0.5, 0.5)//右
  27.     }
  28.    
  29.  
  30.     //衝突のグループ分けした物体作成
  31.     private function makeGroup():void {
  32.        
  33.         //表示用Sprite
  34.         var disp_box = new Sprite();
  35.         this.addChild(disp_box);
  36.        
  37.         var disp_item = new Sprite();
  38.         this.addChild(disp_item);
  39.        
  40.        
  41.         var i:int;
  42.         var s_item_num:int = 3;
  43.        
  44.         var item_size:int = 40;
  45.         var box_size:int = 100;
  46.        
  47.         var category_bit:uint;
  48.         var mask_bit:uint;
  49.        
  50.        
  51.         //赤と赤、緑と緑、赤と緑は衝突
  52.         //壁とも衝突
  53.        
  54.         //赤色
  55.         category_bit = 0x0002; // 0000 0000 0000 0010
  56.         mask_bit =     0x0007; // 0000 0000 0000 0111
  57.        
  58.         var box_red:Sprite = new box_red_mc as Sprite;
  59.         this.setBox(box_size, box_size, 120, 150, box_red, disp_box, category_bit, mask_bit);
  60.  
  61.         for (i = 0; i <s_item_num; i++) {
  62.             var kinoko_red:Sprite = new kinoko_red_mc as Sprite;
  63.             this.setCircle(item_size, Math.random() * 500, 20, kinoko_red, disp_item, category_bit, mask_bit);
  64.         }
  65.        
  66.         //緑色
  67.         category_bit = 0x0004; // 0000 0000 0000 0100
  68.         mask_bit =     0x0007; // 0000 0000 0000 0111
  69.        
  70.         var box_green:Sprite = new box_green_mc as Sprite;
  71.         this.setBox(box_size, box_size, 240, 350, box_green, disp_box, category_bit, mask_bit);
  72.  
  73.         for (i = 0; i <s_item_num; i++) {
  74.             var kinoko_green:Sprite = new kinoko_green_mc as Sprite;
  75.             this.setCircle(item_size, Math.random() * 500, 20, kinoko_green, disp_item, category_bit, mask_bit);
  76.         }
  77.        
  78.        
  79.         //黄と黄は衝突
  80.         //壁とも衝突
  81.        
  82.         //黄色
  83.         category_bit = 0x0011; // 0000 0000 0001 0001
  84.         mask_bit =     0x0011; // 0000 0000 0001 0001
  85.        
  86.         var box_yellow:Sprite = new box_yellow_mc as Sprite;
  87.         this.setBox(box_size, box_size, 480, 350, box_yellow, disp_box, category_bit, mask_bit);
  88.  
  89.         for (i = 0; i <s_item_num; i++) {
  90.             var kinoko_yellow:Sprite = new kinoko_yellow_mc as Sprite;
  91.             this.setCircle(item_size, Math.random() * 500, 20, kinoko_yellow, disp_item, category_bit, mask_bit);
  92.         }
  93.  
  94.  
  95.         //青は壁以外衝突しない(青と青も衝突しない)
  96.  
  97.         //青色
  98.         category_bit = 0x0008; // 0000 0000 0000 1000
  99.         mask_bit =     0x0001; // 0000 0000 0000 0001
  100.        
  101.         var box_blue:Sprite = new box_blue_mc as Sprite;
  102.         this.setBox(box_size, box_size, 360, 150, box_blue, disp_box, category_bit, mask_bit);
  103.  
  104.         for (i = 0; i <s_item_num; i++) {
  105.             var kinoko_blue:Sprite = new kinoko_blue_mc as Sprite;
  106.             this.setCircle(item_size, Math.random() * 500, 20, kinoko_blue, disp_item, category_bit, mask_bit);
  107.         }         
  108.     }
  109.    
  110.    
  111.     //四角い物体作成
  112.     private function setBox(w:Number, h:Number, x:Number, y:Number, disp_block:Sprite, disp_blocks:Sprite, category_bits:uint, mask_bit:uint):void {
  113.        
  114.         disp_block.width = w;
  115.         disp_block.height = h;
  116.        
  117.         var block:b2Body = this.makeB2BodyBox(w, h, x, y, 0, 0, 0.5, 0.5, disp_block, disp_blocks);
  118.         block.m_shapeList.m_filter.categoryBits = category_bits;
  119.         block.m_shapeList.m_filter.maskBits = mask_bit;
  120.        
  121.         //フィルターの更新
  122.         this.m_b2_world.Refilter(block.m_shapeList);           
  123.     }
  124.    
  125.    
  126.     //丸い物体作成
  127.     private function setCircle(size:Number, x:Number, y:Number, disp_block:Sprite, disp_blocks:Sprite, category_bits:uint, mask_bit:uint):void {
  128.        
  129.         disp_block.width = size;
  130.         disp_block.height = size;
  131.        
  132.         var block:b2Body = this.makeB2BodyCircle(size, x, y, 1, 0.5, 0.5, disp_block, disp_blocks);
  133.         block.m_shapeList.m_filter.categoryBits = category_bits;
  134.         block.m_shapeList.m_filter.maskBits = mask_bit;
  135.        
  136.         //フィルターの更新
  137.         this.m_b2_world.Refilter(block.m_shapeList);           
  138.     }      
  139.    
  140.    
  141.     //演算
  142.     private function update(e:Event):void {
  143.  
  144.         m_b2_world.Step(m_b2_timeStep, m_b2_iterations);
  145.        
  146.         for (var bb:b2Body = m_b2_world.m_bodyList; bb; bb = bb.m_next){
  147.            
  148.             if (bb.m_userData is Sprite){
  149.                 bb.m_userData.x = bb.GetPosition().x * m_b2_physcale;
  150.                 bb.m_userData.y = bb.GetPosition().y * m_b2_physcale;
  151.                 bb.m_userData.rotation = bb.GetAngle() * (180 / Math.PI);
  152.             }
  153.         }
  154.        
  155.         //衝突判定
  156.         for (var cbb:b2Contact = m_b2_world.m_contactList; cbb; cbb = cbb.m_next) {
  157.            
  158.             var userdata1:MovieClip = cbb.m_shape1.m_body.m_userData as MovieClip;
  159.             if (userdata1 is Sprite) {
  160.                 userdata1.gotoAndPlay("contact");
  161.             }
  162.            
  163.             var userdata2:MovieClip = cbb.m_shape2.m_body.m_userData as MovieClip;
  164.             if (userdata2 is Sprite) {
  165.                 userdata2.gotoAndPlay("contact");
  166.             }
  167.         }
  168.        
  169.         //マウスジョイント
  170.         this.updateMouseWorld();
  171.         this.mouseDrag();
  172.     }
  173.    
  174.     //マウスジョイント設定    ---------------------------------------------------------------------
  175.     //Box2D付属のGeneralのInputをほぼこコピペ
  176.    
  177.     // world mouse position
  178.     private var m_mouseJoint:b2MouseJoint;  //マウスジョイント
  179.    
  180.     private var m_mouseXWorldPhys:Number//メートル単位のマウス座標
  181.     private var m_mouseYWorldPhys:Number;
  182.  
  183.     private var m_mouse_dowm:Boolean = false//マウスボタン押されてるか
  184.    
  185.     private function onMouseDown(e:Event):void {
  186.         this.m_mouse_dowm = true;
  187.     }
  188.    
  189.     private function onMouseUp(e:Event):void {
  190.         this.m_mouse_dowm = false;
  191.     }
  192.    
  193.     //マウス座標取得
  194.     public function updateMouseWorld():void{
  195.         //メートル単位のマウス座標に変換
  196.         m_mouseXWorldPhys = this.mouseX / this.m_b2_physcale;
  197.         m_mouseYWorldPhys = this.mouseY / this.m_b2_physcale;
  198.     }
  199.    
  200.     //マウスドラッグ時
  201.     public function mouseDrag():void{
  202.        
  203.         //マウスボタン押した(ジョイントまだ)
  204.         if (this.m_mouse_dowm && !this.m_mouseJoint){
  205.            
  206.             var body:b2Body = GetBodyAtMouse()//マウスの下の物体取得
  207.  
  208.             if (body)
  209.             {
  210.                 var md:b2MouseJointDef = new b2MouseJointDef();
  211.                 md.body1 = this.m_b2_world.GetGroundBody();
  212.                 md.body2 = body;
  213.                 md.target.Set(this.m_mouseXWorldPhys, this.m_mouseYWorldPhys);
  214.                 md.maxForce = 300000.0 * body.GetMass();
  215.                 md.timeStep = this.m_b2_timeStep;
  216.                 m_mouseJoint = this.m_b2_world.CreateJoint(md) as b2MouseJoint;
  217.                 body.WakeUp();
  218.             }
  219.         }
  220.        
  221.        
  222.         //マウスボタン離した
  223.         if (!this.m_mouse_dowm){
  224.             if (this.m_mouseJoint)
  225.             {
  226.                 this.m_b2_world.DestroyJoint(m_mouseJoint);
  227.                 m_mouseJoint = null;
  228.             }
  229.         }
  230.        
  231.        
  232.         //マウス押されてる状態(ジョイントされてる)
  233.         if (this.m_mouse_dowm && this.m_mouseJoint)
  234.         {
  235.             var p2:b2Vec2 = new b2Vec2(this.m_mouseXWorldPhys, this.m_mouseYWorldPhys);
  236.             m_mouseJoint.SetTarget(p2);
  237.         }
  238.     }
  239.    
  240.    
  241.     //マウスの下の物体取得
  242.     private var mousePVec:b2Vec2 = new b2Vec2();
  243.     public function GetBodyAtMouse(includeStatic:Boolean=false):b2Body{
  244.         // Make a small box.
  245.         mousePVec.Set(this.m_mouseXWorldPhys, this.m_mouseYWorldPhys);
  246.         var aabb:b2AABB = new b2AABB();
  247.         aabb.lowerBound.Set(this.m_mouseXWorldPhys - 0.001, this.m_mouseYWorldPhys - 0.001);
  248.         aabb.upperBound.Set(this.m_mouseXWorldPhys + 0.001, this.m_mouseYWorldPhys + 0.001);
  249.        
  250.         // Query the world for overlapping shapes.
  251.         var k_maxCount:int = 10;
  252.         var shapes:Array = new Array();
  253.         var count:int = this.m_b2_world.Query(aabb, shapes, k_maxCount);
  254.         var body:b2Body = null;
  255.         for (var i:int = 0; i <count; ++i)
  256.         {
  257.             if (shapes[i].GetBody().IsStatic() == false || includeStatic)
  258.             {
  259.                 var tShape:b2Shape = shapes[i] as b2Shape;
  260.                 var inside:Boolean = tShape.TestPoint(tShape.GetBody().GetXForm(), mousePVec);
  261.                 if (inside)
  262.                 {
  263.                     body = tShape.GetBody();
  264.                     break;
  265.                 }
  266.             }
  267.         }
  268.         return body;
  269.     }
  270.    
  271. }