太久沒有更新了,新年回來工作,突然有收到網友的郵件提問,居然還有人在關注,慚愧,找了下電腦上還有一點兒存著,順便先發這一個番外篇吧,好歹可以看到真實的效果,等我考完英語,一定會更新下一章,“憤怒的小鳥篇”
此篇,並不是書中的篇符,而是通過希望通過結合實際的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