前回に続きまして、四角の一人四角遊びです(?)
画面をクリックした後、「←」「→」で左右移動、「s」キーでジャンプです。
前回同様、「s」キー連打で多段ジャンプ!
↓参考にさせていただきました。
■Box2Dサンプル maskBitsによる衝突フィルタリング
今回やりたかったのは、上からものを落として、
何回かぶつかったら、部屋から立ち去らせるということ。
具体的には、
3回、床との衝突を検知したら、
落ちてくる箱の衝突フィルタの値を変更するということをやりたかった。
箱を定義するときにIDを指定しておくことで、何と何が衝突したか検知できる。
ACTIONSCRIPT:
- var floorBodyDef:b2BodyDef = new b2BodyDef();
- // 床のIDを floor としておく
- floorBodyDef.userData = new Object;
- floorBodyDef.userData.id = "floor";
- floorBodyDef.position.Set(6, 8);
3回衝突を検知したら、maskBitsの値を0x00に変更して、誰とも衝突しないようにする。
Box2Dのソースから追って、filterを再度ゲットできるところを探したんだけど、
これでよかったんだろうか。
ACTIONSCRIPT:
- for (var ce:b2ContactEdge = floor.m_contactList; ce != null; ce = ce.next) {
- var obj1:b2Body = ce.contact.GetShape1().m_body;//1つ目のオブジェクト
- var obj2:b2Body = ce.contact.GetShape2().m_body;//2つ目のオブジェクト
- if(obj1.m_userData && obj2.m_userData && ce.contact.GetManifoldCount() == 1){
- if(obj2.m_userData.id == "dropbox"){
- if (obj2.m_userData.crash> 2){
- shape = obj2.GetShapeList();
- shape.m_filter.maskBits = 0x00;
- }else {
- obj2.m_userData.crash++;
- }
- }
- }
- }
だいぶ作りたいものに近づいてきました!
次はShapeで絵をちゃんと重ねよう!
↓ソース全部
ACTIONSCRIPT:
- package src {
- import Box2D.Collision.b2AABB;
- import Box2D.Collision.b2ContactID;
- import Box2D.Collision.Shapes.b2CircleDef;
- import Box2D.Collision.Shapes.b2PolygonDef;
- import Box2D.Collision.Shapes.b2Shape;
- import Box2D.Common.Math.b2Vec2;
- import Box2D.Dynamics.b2Body;
- import Box2D.Dynamics.b2BodyDef;
- import Box2D.Dynamics.b2DebugDraw;
- import Box2D.Dynamics.b2World;
- import Box2D.Dynamics.Contacts.b2ContactEdge;
- import flash.display.Sprite;
- import flash.events.Event;
- import flash.events.KeyboardEvent;
- import flash.events.MouseEvent;
- import flash.events.TextEvent;
- import flash.text.TextField;
- import flash.ui.Keyboard;
- import flash.utils.*;
- /**
- * @author okm
- */
- public class LabyrinsSuite extends Sprite{
- private var world:b2World;
- private var square:b2Body;
- private var floor:b2Body;
- public function LabyrinsSuite() {
- var textField:TextField = new TextField;
- textField.text = "click me ";
- textField.x = 100;
- textField.y = 100;
- textField.selectable = false;
- this.addChild(textField);
- stage.addEventListener(MouseEvent.CLICK, go);
- }
- public function go(event:MouseEvent):void {
- stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
- stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
- ////////////////////////////////////////
- // 物理エンジンのセットアップ
- // 縦横200メートルの世界を作成
- 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);
- /////////////////////////////////////////////
- // 部屋の作成 横幅 12M 高さ 8M の部屋を作成
- /////////////////////////////////////////////
- // 床
- // 天井の高さは 8M 床の 中心X座標は 7.5M(真ん中)
- var floorBodyDef:b2BodyDef = new b2BodyDef();
- // 床のIDを floor としておく
- floorBodyDef.userData = new Object;
- floorBodyDef.userData.id = "floor";
- floorBodyDef.position.Set(6, 8);
- // 床の形を、幅12m、厚さ20cmとする
- // 指定するのはその半分の値
- var floorShapeDef:b2PolygonDef = new b2PolygonDef();
- floorShapeDef.friction = 0.1;
- floorShapeDef.SetAsBox(6, 0.1);
- // 床のcategoryBits/maskBits
- floorShapeDef.filter.maskBits = 0x01;
- floorShapeDef.filter.categoryBits = 0x01;
- // 床を動かない物体として作る
- floor = world.CreateBody(floorBodyDef);
- floor.CreateShape(floorShapeDef);
- // 両端の壁 高さは 8M 幅 10cm
- // 左壁
- var leftWallBodyDef:b2BodyDef = new b2BodyDef();
- leftWallBodyDef.userData = new Object;
- leftWallBodyDef.userData.id = "left";
- leftWallBodyDef.position.Set(0.05, 4);
- var wallShapeDef:b2PolygonDef = new b2PolygonDef();
- wallShapeDef.friction = 0;
- wallShapeDef.SetAsBox(0.05, 4);
- var leftWall:b2Body = world.CreateBody(leftWallBodyDef);
- leftWall.CreateShape(wallShapeDef);
- // 右壁
- var rightWallBodyDef:b2BodyDef = new b2BodyDef();
- rightWallBodyDef.userData = new Object;
- rightWallBodyDef.userData.id = "right";
- rightWallBodyDef.position.Set(11.95, 4);
- var rightWall:b2Body = world.CreateBody(rightWallBodyDef);
- rightWall.CreateShape(wallShapeDef);
- ////////////////////////////////////////
- // 箱生命体
- ////////////////////////////////////////
- // 箱の位置を左から2.5m、上から1mとする
- var boxBodyDef:b2BodyDef = new b2BodyDef();
- boxBodyDef.userData = new Object;
- boxBodyDef.userData.id = "hako";
- boxBodyDef.position.Set(2.5, 1);
- // 箱の幅 60cm 高さ 1M 重さは 30kg とする
- var boxShapeDef:b2PolygonDef= new b2PolygonDef();
- //boxShapeDef.SetAsOrientedBox(0.3, 0.2, new b2Vec2(0, 0), 0.8);
- boxShapeDef.SetAsBox(0.6, 1);
- boxShapeDef.density = 50; // 密度 [kg/m^2] 30/0.6*1
- boxShapeDef.friction = 0.2; // 摩擦係数
- boxShapeDef.restitution = 0.3; // 反発係数、通常は0~1
- // 箱を動く物体として作る
- var boxBody:b2Body = world.CreateBody(boxBodyDef);
- boxBody.CreateShape(boxShapeDef);
- // SetMassFromShapes で重力が有効になる
- boxBody.SetMassFromShapes();
- square = boxBody;
- ////////////////////////////////////////
- // 描画設定
- var debugDraw:b2DebugDraw = new b2DebugDraw();
- debugDraw.m_sprite = this;
- debugDraw.m_drawScale = 45; // 1mを45ピクセルにする
- debugDraw.m_fillAlpha = 0.3; // 不透明度
- debugDraw.m_lineThickness = 1; // 線の太さ
- debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
- world.SetDebugDraw(debugDraw);
- this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
- setInterval(dropBox, 700);
- }
- private function dropBox():void {
- var dropbox_x:Number = this.xRandomInt(11, 1);
- var dropboxBodyDef:b2BodyDef = new b2BodyDef();
- dropboxBodyDef.userData = new Object;
- dropboxBodyDef.userData.id = "dropbox";
- dropboxBodyDef.userData.crash = 0;
- dropboxBodyDef.angle = this.xRandomInt(5, 0) / 10;
- dropboxBodyDef.position.Set(dropbox_x, 0.5);
- // 箱の幅 15cm 高さ 15cm 重さは 1kg とする
- var dropboxShapeDef:b2PolygonDef= new b2PolygonDef();
- //boxShapeDef.SetAsOrientedBox(0.3, 0.2, new b2Vec2(0, 0), 0.8);
- dropboxShapeDef.SetAsBox(0.15, 0.15);
- dropboxShapeDef.density = 25; // 密度
- dropboxShapeDef.friction = 0.2; // 摩擦係数
- dropboxShapeDef.restitution = 0.7; // 反発係数、通常は0~1
- // 箱を動く物体として作る
- var dropboxBody:b2Body = world.CreateBody(dropboxBodyDef);
- //dropboxBody.CreateShape(dropboxShapeDef);
- // SetMassFromShapes で重力が有効になる
- //dropboxBody.SetMassFromShapes();
- // ボールのcategoryBits/maskBits
- dropboxShapeDef.filter.categoryBits = 0x01;
- dropboxShapeDef.filter.maskBits = 0x01;
- var dropbox:b2Body = world.CreateBody(dropboxBodyDef);
- dropbox.CreateShape(dropboxShapeDef);
- dropbox.SetMassFromShapes();
- }
- private var m_InputL:Number = 0;
- private var m_InputR:Number = 0;
- private var m_InputS:Number = 0;
- private var m_Dir:Number = 0;
- private var moveTime:Number = 0;
- // キーが押されたときの処理
- private function keyDownHandler(event:KeyboardEvent):void {
- square.WakeUp();
- if(event.keyCode == Keyboard.LEFT && m_InputL != 1){
- m_InputL = 1;
- m_InputR = 0;
- m_Dir = -1.0;
- moveTime = 0;
- }
- if(event.keyCode == Keyboard.RIGHT && m_InputR != 1){
- m_InputR = 1;
- m_InputL = 0;
- m_Dir = 1.0;
- moveTime = 0;
- }
- if(event.keyCode == 83){ // s
- m_InputS = 1;
- }
- }
- private function keyUpHandler(event:KeyboardEvent):void {
- if(event.keyCode == Keyboard.LEFT){
- m_InputL = 0;
- }
- if(event.keyCode == Keyboard.RIGHT){
- m_InputR = 0;
- }
- if(event.keyCode == 83){ // s
- m_InputS = 0;
- }
- }
- private function enterFrameHandler(event:Event):void {
- if (m_InputS == 1) {
- square.m_linearVelocity.y = -4;
- }
- if (m_InputL> 0) {
- var leftForce:Number = this.easeInOutQuad(moveTime, 0.5, 6, 30);
- if (moveTime <30) moveTime++;
- square.m_linearVelocity.x = -leftForce;
- }
- if (m_InputR> 0) {
- var rightForce:Number = this.easeInOutQuad(moveTime, 0.5, 6, 30);
- if (moveTime <30) moveTime++;
- square.m_linearVelocity.x = rightForce;
- }
- if (world == null) {
- return;
- }
- var shape:b2Shape;
- // 衝突判定 箱生命体
- /* 今回はとりあえず箱との衝突はカウントしない方向で。
- for (var ce:b2ContactEdge = square.m_contactList; ce != null; ce = ce.next) {
- var obj1:b2Body = ce.contact.GetShape1().m_body;//1つ目のオブジェクト
- var obj2:b2Body = ce.contact.GetShape2().m_body;//2つ目のオブジェクト
- if(obj1.m_userData && obj2.m_userData && ce.contact.GetManifoldCount() == 1){
- if (obj2.m_userData.id == "dropbox") {
- if (obj2.m_userData.crash> 2){
- shape = obj2.GetShapeList();
- shape.m_filter.maskBits = 0x00;
- }else {
- obj2.m_userData.crash++;
- }
- }
- }
- }
- */
- // 衝突判定 床
- for (var ce:b2ContactEdge = floor.m_contactList; ce != null; ce = ce.next) {
- var obj1:b2Body = ce.contact.GetShape1().m_body;//1つ目のオブジェクト
- var obj2:b2Body = ce.contact.GetShape2().m_body;//2つ目のオブジェクト
- if(obj1.m_userData && obj2.m_userData && ce.contact.GetManifoldCount() == 1){
- if(obj2.m_userData.id == "dropbox"){
- if (obj2.m_userData.crash> 2){
- shape = obj2.GetShapeList();
- shape.m_filter.maskBits = 0x00;
- }else {
- obj2.m_userData.crash++;
- }
- }
- }
- }
- // Flashはデフォルトで秒間24フレームなので、
- // 物理シミュレーションを1/24秒進める
- world.Step(1 / 24, 10);
- }
- /**
- * t = time
- * b = beginning value
- * c = change in value
- * d = duration
- */
- public function easeInOutQuad(t:Number, b:Number, c:Number, d:Number):Number {
- if ((t/=d/2) <1) return c/2*t*t + b;
- return -c/2 * ((--t)*(t-2) - 1) + b;
- };
- public function xRandomInt (nMax:Number, nMin:Number):Number {
- // nMinからnMaxまでのランダムな整数を返す
- var nRandomInt:Number = Math.floor(Math.random()*(nMax-nMin+1))+nMin;
- return nRandomInt;
- }
- }
- }
- Newer: wordpress に addthis を追加
- Older: Box2Dで 四角の一人ボール遊び
Comments:1
- okm 08-07-07 (月) 15:09
-
あぁ・・・スリープ状態になって、落ち着く四角たちがいる・・・まぁいいや・・・。
Trackbacks:0
- Trackback URL for this entry
- http://parpue.net/web/35/trackback
- Listed below are links to weblogs that reference
- Box2d で降りしきる箱と戯れる箱 from parpue.net


