HTML5之2D物理引擎 Box2D for javascript Games 系列 翻外篇--如何結合createJS應用box2d.js


太久沒有更新了,新年回來工作,突然有收到網友的郵件提問,居然還有人在關注,慚愧,找了下電腦上還有一點兒存着,順便先發這一個番外篇吧,好歹可以看到真實的效果,等我考完英語,一定會更新下一章,“憤怒的小鳥篇”


 

此篇,並不是書中的篇符,而是通過希望通過結合實際的canvas 繪圖庫實現box2d物理引擎在各繪圖庫上應用,繪圖庫網上有很多現成的

如:createjs, pixi.js 等,Egret或者其它游戲引擎有自己的物理引擎擴展庫,所以就不說了。

現在通過之前的學習,基本掌握了剛體等基礎概念。那如何如何應用於現實畫面中呢?

box2d只是模擬了物體,是虛擬的,如果不是通過debug是看不到任何畫面的,要讓用戶看到畫面,必須得結合canvas繪圖能力,自己操作canvas繪圖的原始API太麻煩,所以就有了createjs等其它流行的canvas庫.

以下都以createJS代替canvas,當然你用其它庫或者直接操作canvas也都可以


 

先上效果圖

 

完成代碼位於

https://github.com/willian12345/Box2D-for-Javascript-Games/blob/master/5-c.html

 

box2d呈現於createJS,貼上圖的基本原理,就是將物理引擎世界中剛體的所有狀態復制到createJS舞台對象!

 

function init() {
         var   b2Vec2 = Box2D.Common.Math.b2Vec2
            ,  b2AABB = Box2D.Collision.b2AABB
            ,  b2BodyDef = Box2D.Dynamics.b2BodyDef
            ,  b2Body = Box2D.Dynamics.b2Body
            ,  b2FixtureDef = Box2D.Dynamics.b2FixtureDef
            ,  b2Fixture = Box2D.Dynamics.b2Fixture
            ,  b2World = Box2D.Dynamics.b2World
            ,  b2MassData = Box2D.Collision.Shapes.b2MassData
            ,  b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape
            ,  b2CircleShape = Box2D.Collision.Shapes.b2CircleShape
            ,  b2DebugDraw = Box2D.Dynamics.b2DebugDraw
            ,  b2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef
            ;
         var worldScale = 30; // box2d中以米為單位,1米=30像素
         var gravity = new b2Vec2(0, 5);
         var sleep = true;
         var world;
         var stage,debug;


         function main(){
            stage = new createjs.Stage("canvas");
            debug = new createjs.Stage("debug");

            setupPhysics();

            debugDraw();

            debug.on("stagemousedown", stagemousedown);

            createjs.Ticker.timingMode = createjs.Ticker.RAF;
            createjs.Ticker.on("tick", function(){
               stage.update();
               world.DrawDebugData(); // 為了顯示出createjs對象,這里不再繪制box2d對象至canvas
               world.Step(1/30, 10, 10);// 更新世界模擬
               world.ClearForces(); // 清除作用力
            });
         }
         main();


         function Ball(){
            this.view = new createjs.Bitmap('soccer.png');
            this.view.regX = this.view.regY = 50;

            // 創建box2d球形體
            var bodyDef = new b2BodyDef();
            bodyDef.position.Set(Math.random()*640 / worldScale, 0/worldScale);
            bodyDef.type = b2Body.b2_dynamicBody
            bodyDef.userData = 0;
            var circleShape = new b2CircleShape(50 / worldScale);
            var fixtureDef = new b2FixtureDef();
            fixtureDef.shape = circleShape;
            fixtureDef.density = 1;
            fixtureDef.restitution = .4
            fixtureDef.friction = .5;
            this.view.body = world.CreateBody(bodyDef);
            this.view.body.CreateFixture(fixtureDef);

            this.view.on("tick", function(){
               // 讓createjs的bitmap對象實時復制box2d對象的位置與旋轉角度
               this.x = this.body.GetPosition().x * worldScale;
               this.y = this.body.GetPosition().y * worldScale;
               this.rotation = this.body.GetAngle() * (180 / Math.PI);
            });
         }
         
         function setupPhysics(){
            world = new b2World(new b2Vec2(0, 50), true);
            floor();  
         }

         function stagemousedown(){
            var b = new Ball();
            stage.addChild(b.view); // 將產生的createjs對象添加至舞台上
         }

         function floor(){
            var bodyDef = new b2BodyDef();
            bodyDef.position.Set(320/worldScale, 465/worldScale);
            var polygonShape = new b2PolygonShape();
            polygonShape.SetAsBox(320/worldScale, 15/worldScale);
            var fixtureDef = new b2FixtureDef();
            fixtureDef.shape = polygonShape;
            fixtureDef.restitution = .4;
            fixtureDef.friction = .5;
            var theFloor = world.CreateBody(bodyDef);
            theFloor.CreateFixture(fixtureDef);
         }

         //setup debug draw
         function debugDraw(){
            var debugDraw = new b2DebugDraw();
            debugDraw.SetSprite(debug.canvas.getContext('2d'));
            debugDraw.SetDrawScale(worldScale);
            debugDraw.SetFillAlpha(0.5);
            debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
            world.SetDebugDraw(debugDraw);
         }
      };

 

這一句

this.view = new createjs.Bitmap('soccer.png');

通過createjs的Bitmap對象讀取圖片,創建一個足球

this.view這個顯示對象即createjs的Bitmap對象,用於顯示在舞台即canvas上

this.view.on("tick", function(){
               // 讓createjs的bitmap對象實時復制box2d對象的位置與旋轉角度
               this.x = this.body.GetPosition().x * worldScale;
               this.y = this.body.GetPosition().y * worldScale;
               this.rotation = this.body.GetAngle() * (180 / Math.PI);
            });

在Bitmap對象上偵聽tick事件,tick事件可以理解為FLASH中的ENTER_FRAME事件,即每一幀調用一次,在每幀中將剛體的x,y位置屬性與角度屬性復制到createJS的顯示對象上,就完成了結合

 

注釋掉這一句,就可以隱藏掉box2Djs的調試狀態變成一個正常的帶物理效果的足球了

// debugDraw();

 


 

更多關於createJS請至官網或者搜索相關知識,你也完成可以用其它繪圖庫完成一樣的操作,比如Pixi.js

相關系列:

HTML5之2D物理引擎 Box2D for javascript Games 系列 第一部分

 

注:轉載請注明出處博客園:sheldon(willian12345@126.com)

https://github.com/willian12345


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM