HTML5之2D物理引擎 Box2D for javascript Games 系列 第三部分之建立圖騰破壞者的關卡

建立圖騰破壞者的關卡


 

如今你有能力建立你的第一個遊戲原型,咱們將從建立圖騰破壞者的級別開始。html

爲了展現咱們所作事情的真實性,咱們將流行的Flash遊戲圖騰破壞者的一關做爲 咱們模仿的對象。請看下面的截圖: git

 

這是圖騰破壞者遊戲原型的第一關,若是你仔細觀察你會發現磚塊的尺寸是30的倍 數。你知道這是什麼緣由嗎?若是在你認真學習了前面的章節,你就會知道這是將米 和像素的轉換所致。github

做者建立遊戲多是直接使用米做爲度量單位的,可是咱們將堅持本身的選擇使用像素做爲度量單位。canvas

目前,咱們無需去擔憂怎樣設置褐色和黑色的圖騰顏色,咱們只要想着再現圖騰便可。學習

在咱們開始編碼以前,我將建議你建立幾個方法,這樣能夠幫咱們重用部分代碼。別擔憂,沒什麼新的東西,咱們只是稍微組織一下咱們的腳本。測試

 

一、所以,咱們將建立一個debugDraw()方法,它將處理全部與調試繪圖編碼

function debugDraw(){
            var debugDraw = new b2DebugDraw();
            debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
            debugDraw.SetDrawScale(worldScale);
            debugDraw.SetFillAlpha(0.5);
            debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
            world.SetDebugDraw(debugDraw);
}

二、而後,因爲咱們要建立不少的磚塊,因此我強烈推薦用一個方法經過磚 塊的位置和尺寸來建立磚塊,因此下面的brick()方法的參數爲:磚塊原點 的水平和垂直座標,寬度和高度。spa

function brick(px, py, w, h){

            var bodyDef = new b2BodyDef();
            bodyDef.position.Set(px/worldScale, py/worldScale);
            //bodyDef.type = b2Body.b2_dynamicBody;
            var polygonShape = new b2PolygonShape();
            polygonShape.SetAsBox(w/2/worldScale, h/2/worldScale); var fixtureDef = new b2FixtureDef();
            fixtureDef.shape = polygonShape;
            fixtureDef.density = 2;
            fixtureDef.restitution = .4;
            fixtureDef.friction = .5;
            var theBrick = world.CreateBody(bodyDef);
            theBrick.CreateFixture(fixtureDef);
         }

 

若是你看看代碼就會發現沒有什麼新東西,可是我但願你能看看突出顯示的那幾行代碼: debug

 

°  首先,被註釋了的那行設置類型屬性的代碼, 所以目前咱們建立的都 是static類型的剛體。當你在設置關卡的時候,使用static類型的剛體比 較好,一旦你滿意你所設計的關卡時,能夠將它們轉變爲dynamic類型 的剛體。static類型的剛體將幫助你查看每個剛體的精確位置,避免 重疊或其它的設計錯誤。 
設計

 

°  其次,在SetAsBox()方法中, 咱們將磚塊的寬高分別除以2再除以以前 的worldScale。不管它要的是磚塊的半寬和半高,我這麼作是想要用真 實的寬高像素來調用brick()方法,

 

三、 你的Main類的方法應該看起來向下面這樣: 

function main(){
            world = new b2World(gravity, sleep);
            debugDraw();
           // level design goes here 
            setInterval(updateWorld, 1000 / 60);
         }

如今Main()方法看起來簡單清晰,那麼咱們能夠經過調用brick()方法,一次一 塊的來搭建咱們的關卡。

而且,請注意我將重力(gravity)設置爲(0,5)而不是做爲小球下落時的真 實世界的重力。較弱的重力將會使圖騰破壞和下落變得慢一些,從而產生更 好的效果。總之,這只是個與遊戲設計的建議,並且你能夠自由設置你本身 的重力。

 

四、如今,讓咱們回到Main()方法中: 

function main(){
            world = new b2World(gravity, sleep);
            debugDraw();
            brick(275,435,30,30);
            brick(365,435,30,30);
            brick(320,405,120,30);
            brick(320,375,60,30);
            brick(305,345,90,30);
            brick(320,300,120,60);
            setInterval(updateWorld, 1000 / 60);
         }

咱們先搭建左邊的基石磚塊和右邊的基石磚塊,而後剩下的磚塊從下向上一次堆放。

 

五、測試你的影片

完整源碼在demo2-4.html中查看

 

我想你會爲你的測試成功而感到很是的開心。正如你學習搭建你的第一個圖騰那 樣,咱們準備將黃金神像放到圖騰的頂部。在咱們添加地面和改變圖騰剛體爲dynamic類型以前,我但願你思考一下黃金神 像。 假使咱們想要給黃金神像一個形狀,而這個形狀是不一樣於矩形和圓形的形狀,這將會怎樣呢?


 

 

建立複合剛體

黃金神像在圖騰破壞者中是主要角色,咱們不能用一個矩形來表明它或者不然詛咒的圖騰將會永遠困擾着咱們。

我想象出了下面的圖形:

這就我說的黃金神像,就是咱們將要在Box2D中建立的物體。

上圖的左邊是神像剛體的輪廓,而後右邊是完成的神像輪廓。

首先你看到的神像是由不止一個剛體組合而成的一個複雜剛體。記住Box2D只能接受 凸多邊形。和圖騰磚塊只是單個的堆疊不一樣,咱們須要經過某種方法合併全部的神像 組成對象。

首先,咱們將從建立一個垂直的矩形開始,這個咱們已經知道怎樣建立了,咱們將把 它的代碼放在Main()方法中最後一塊圖騰磚塊以後。

function main(){
            world = new b2World(gravity, sleep);
            debugDraw();
            brick(275,435,30,30);
            brick(365,435,30,30);
            brick(320,405,120,30);
            brick(320,375,60,30);
            brick(305,345,90,30);
            brick(320,300,120,60);
            idol(320, 242);
            setInterval(updateWorld, 1000 / 60);
         }

下面的idol()方法是咱們建立神像的方法: 

function idol(px, py){
            var bodyDef = new b2BodyDef();
            bodyDef.position.Set(px/worldScale, py/worldScale);
            //bodyDef.type = b2Body.b2_dynamicBody;
            var polygonShape = new b2PolygonShape();
            polygonShape.SetAsBox(5/worldScale, 20/worldScale);
            var fixtureDef = new b2FixtureDef();
            fixtureDef.shape = polygonShape;
            fixtureDef.density = 1;
            fixtureDef.restitution = .4;
            fixtureDef.friction = .5;
            var theIdol = world.CreateBody(bodyDef);
            theIdol.CreateFixture(fixtureDef);
         }

目前,咱們只添加了一個矩形形狀,就和磚塊同樣,因此這些代碼無需說明。

測試影片,你將會看到神像的剛體。

完整源碼在demo2-5.html中查看

 

 

第二部分,咱們將建立一個交叉的形狀。這個交叉的形狀是由兩個矩形組成,可是 此次他們分別要順時針和逆時針旋轉45度。

 

你將在下面學到建立定向的矩形形狀。

 


 

建立定向的矩形

建立定向矩形形狀,我將使用b2PolygonShape類中和SetAsBox()方法類似的 SetAsOrientedBox()加強方法。 參數是矩形的寬和高,矩形的中心定義是一個b2Vec2對象和旋轉的弧度。

一、應用上面的方法,在idol()方法中按照下面的步驟操做: 

var bW = 5/worldScale;
var bH = 20/worldScale;
var boxPos = new b2Vec2(0, 10/worldScale);// 可使用矩形內的相對位置
var boxAngle = -Math.PI / 4;

前兩行代碼,咱們定義了矩形的尺寸,和咱們剛剛建立的矩形同樣。

讓咱們來看看第三行,在這裏咱們定義了位置,你可能會有疑惑。第一個神 像的組件矩形的中心爲(320,242)像素,因此爲何我要將第二個神像矩形 的位置設置爲(0,10)?不是應該放置在第一塊神像組件矩形的附近嗎? 這是你須要學習複合對象神奇的地方。如今,咱們不須要定義絕對位置,而是定義一個相對第一個神像組件矩形的位置。因此,這將意味着,矩形將放置在剛體中心偏下的位置。最後一行就是指定旋轉的弧度,逆時針45度。

 

二、你能夠將這四個變量做爲參數傳入SetAsOrientedBox()方法: 


polygonShape.SetAsOrientedBox(bW, bH, boxPos, boxAngle);

三、而後,照例咱們要更新夾具的shape屬性: 

fixtureDef.shape = polygonShape;

四、那麼,神奇的神奇的事情要發生了,我不用去建立一個新b2Body對象,咱們 將夾具附加到已經存在的theIdol剛體上: 

theIdol.CreateFixture(fixtureDef);

五、若是咱們爲交叉形狀的另外一個矩形應用相同的參數,咱們須要改變一下boxAngle變量: 


boxAngle=Math.PI/4;

六、而後咱們能夠建立定向矩形,更新夾具的shape屬性,而後添加它到theIdol剛 體上:

    polygonShape.SetAsOrientedBox(bW, bH, boxPos, boxAngle);
                fixtureDef.shape = polygonShape;
                theIdol.CreateFixture(fixtureDef);

七、最後,idol()方法將看起來和下面的代碼片斷同樣: 

function idol(px, py){
            var bodyDef = new b2BodyDef();
            bodyDef.position.Set(px/worldScale, py/worldScale);
            //bodyDef.type = b2Body.b2_dynamicBody;
            var polygonShape = new b2PolygonShape();
            polygonShape.SetAsBox(5/worldScale, 20/worldScale);
            var fixtureDef = new b2FixtureDef();
            fixtureDef.shape = polygonShape;
            fixtureDef.density = 1;
            fixtureDef.restitution = .4;
            fixtureDef.friction = .5;
            var theIdol = world.CreateBody(bodyDef);
            theIdol.CreateFixture(fixtureDef);

            // 建立定向矩形
            var bW = 5/worldScale;
            var bH = 20/worldScale;
            var boxPos = new b2Vec2(0, 10/worldScale);// 可使用矩形內的相對位置
            var boxAngle = -Math.PI / 4;
            // 左傾矩形
            polygonShape.SetAsOrientedBox(bW, bH, boxPos, boxAngle);
            fixtureDef.shape = polygonShape;
            theIdol.CreateFixture(fixtureDef);

            // 右傾矩形
            boxAngle = Math.PI / 4;
            polygonShape.SetAsOrientedBox(bW, bH, boxPos, boxAngle);
            fixtureDef.shape = polygonShape;
theIdol.CreateFixture(fixtureDef);
}

八、測試影片,咱們將看到神像與以前的圖案比較類似了: 

完整代碼在demo2-6.html

如今,咱們仍須要建立它的頭部。

此次,你應該能夠本身去建立它了吧。總而言之,它只是另外一個複合剛體的定向矩形部件。我將向你展現另一種方式,使用更增強大的方法建立一個多邊形形狀。

 

 

 


 

建立各類類型的凸多邊形

Box2D容許你建立任何種類的多邊形形狀,只要多邊形是凸多邊形,這將意味着它擁 有的全部內角要小於180度,因此全部的頂點要遠離中心,並且你要按順時針順序排 列它們。

 

一、首先,讓咱們建立一個向量(Vector)來儲存全部的頂點: 


// 用多邊形方式建立凸多邊形
var vertices = new b2Vec2();

 

二、而後,咱們將全部頂點做爲b2Vec2對象並順時針順序推入向量(vertices)中, 
併爲b2Vec2對象指派頂點相對神像剛體的中心的座標位置。 


var vertices = new Box2D.NVector();
            vertices.push(new b2Vec2(-15/worldScale,-25/worldScale));
            vertices.push(new b2Vec2(0,-90/worldScale));
            vertices.push(new b2Vec2(15/worldScale, -25/worldScale));
vertices.push(new b2Vec2(0,-10/worldScale));

 

三、以前的幾行代碼表示的是神像的頭部的四個頂點。如今讓咱們將向(vector) 變成多邊形形狀

polygonShape.SetAsVector(vertices, 4);

SetAsVector方法將任何順時針方向的頂點向量(vector)變成一個多邊形形 狀。第二個參數只是表明須要的頂點數。

 

四、最後,和一般同樣,你須要更新夾具的shape屬性並將它添加到theIdol剛 體上 


fixtureDef.shape = polygonShape;
theIdol.CreateFixture(fixtureDef);

五、下面就是idol()方法看起來的樣子:



function idol(px, py){
            var bodyDef = new b2BodyDef();
            bodyDef.position.Set(px/worldScale, py/worldScale);
            bodyDef.type = b2Body.b2_dynamicBody;
            var polygonShape = new b2PolygonShape();
            polygonShape.SetAsBox(5/worldScale, 20/worldScale);
            var fixtureDef = new b2FixtureDef();
            fixtureDef.shape = polygonShape;
            fixtureDef.density = 1;
            fixtureDef.restitution = .4;
            fixtureDef.friction = .5;
            var theIdol = world.CreateBody(bodyDef);
            theIdol.CreateFixture(fixtureDef);

            // 建立定向矩形
            var bW = 5/worldScale;
            var bH = 20/worldScale;
            var boxPos = new b2Vec2(0, 10/worldScale);// 可使用矩形內的相對位置
            var boxAngle = -Math.PI / 4;
            // 左傾矩形
            polygonShape.SetAsOrientedBox(bW, bH, boxPos, boxAngle);
            fixtureDef.shape = polygonShape;
            theIdol.CreateFixture(fixtureDef);

            // 右傾矩形
            boxAngle = Math.PI / 4;
            polygonShape.SetAsOrientedBox(bW, bH, boxPos, boxAngle);
            fixtureDef.shape = polygonShape;
            theIdol.CreateFixture(fixtureDef);

            // 用多邊形方式建立凸多邊形
            var vertices = new Box2D.NVector();
            vertices.push(new b2Vec2(-15/worldScale,-25/worldScale));
            vertices.push(new b2Vec2(0,-90/worldScale));
            vertices.push(new b2Vec2(15/worldScale, -25/worldScale));
            vertices.push(new b2Vec2(0,-10/worldScale));
            polygonShape.SetAsVector(vertices, 4);
            fixtureDef.shape = polygonShape;
            theIdol.CreateFixture(fixtureDef);
         }

六、測試影片而後你將在最後看到你完成的在圖騰頂部的神像

七、這時,你只須要建立地面,它是一個static類型的矩形剛體

function main(){
            world = new b2World(gravity, sleep);
            debugDraw();
            brick(275,435,30,30);
            brick(365,435,30,30);
            brick(320,405,120,30);
            brick(320,375,60,30);
            brick(305,345,90,30);
            brick(320,300,120,60);
            idol(320, 242);
            floor();
            setInterval(updateWorld, 1000 / 60);
         }

八、下面是floor()方法的定義: 

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);
         }

九、而後刪除brick()方法內的註釋行,將磚塊設置爲dynamic類型: 

bodyDef.type = b2Body.b2_dynamicBody;

十、最後,咱們將神像的也設置爲dynamic類型 idol()方法內

bodyDef.type = b2Body.b2_dynamicBody;

 

正如本章開始時所說的,你在Box2D中建立一個真實的圖騰破壞者關卡已經完成

完整代碼請查看demo2-7

概述 

你剛剛學習的是本書中最重要的章節之一,在這裏你學習了怎樣建立剛體而後

使用它們去設計成功遊戲的關卡,例如圖騰破壞者。

 

爲了習慣使用Box2D的剛體,我建議你建立更多的圖騰破壞者(Totem Destroyer)的關卡或者一些紅磚移除(Red Remover)或者憤怒的小鳥(Angry Birds)的關卡。總之,它只是一個簡單的形狀。


 

本文相關代碼請在

https://github.com/willian12345/Box2D-for-Javascript-Games

 

注:轉載請註明出處博客園:sheldon-二狗-偷飯貓(willian12345@126.com)

https://github.com/willian12345

相關文章
相關標籤/搜索