HTML5游戲開發(fā)之將Easel.js和Box2d在畫布中結(jié)合起來
要想學(xué)習(xí)本指南,你應(yīng)該具備box2d和easel的基本知識(shí),知道它們是如何工作的。如何你從沒學(xué)習(xí)過box2d,請(qǐng)閱讀box2d orientation and tutorials。要想學(xué)習(xí)easel,請(qǐng)參考documentation,以學(xué)會(huì)如何往stage中添加對(duì)象,同時(shí)也會(huì)對(duì)顯示的層次結(jié)構(gòu)有個(gè)整體了解。
現(xiàn)在我們開始吧。我們將要?jiǎng)?chuàng)建的是一個(gè)簡單的示例—粉紅色的“鳥雨”。(注意:本示例只有在較新版本的瀏覽器中才可能運(yùn)行)
我們假定讀者已經(jīng)具備了box2d和easel的基本知識(shí),所以將跳過編寫代碼的步驟,直接介紹兩種框架是如何結(jié)合的。如何你想好好研究的話可以下載本示例的zip文件,也可以直接在本頁中查看相關(guān)代碼。
在Easel.js中,往stage中添加對(duì)象是很容易的。下面看一下ticker函數(shù)中是如何將鳥(對(duì)象)添加到屏幕的。(注意:下面這些代碼只是從demo.js中簡單摘錄過來的。如果你想運(yùn)行這些代碼請(qǐng)下載zip.)
- var tick = function(dt, paused) {
- birdDelayCounter++;
- if(birdDelayCounter % 10 === 0) { // delay so it doesn't spawn a bird on every frame
- birdDelayCounter = 0;
- birds.spawn();
- }
- }
- var spawn = function() {
- var birdBMP = new Bitmap("images/bird.png");
- birdBMP.x = Math.round(Math.random()*500);
- birdBMP.y = -30;
- birdBMP.regX = 25; // important to set origin point to center of your bitmap
- birdBMP.regY = 25;
- stage.addChild(birdBMP);
- }
這看起來非常地相象。這些代碼的功能是:向stage中添加鳥(位圖對(duì)象),鳥出現(xiàn)的水平位置是隨機(jī)的,垂直位置在畫布的頂端。位圖對(duì)象可以具有很大的靈活性,你可以把它插到其它位圖中間,可以設(shè)置它的初始位置,也可以使它任意傾斜。
如果想把easel對(duì)象轉(zhuǎn)化為box2d對(duì)象,那么regX和regY(初始位置)是很重要的。因?yàn)椋琤ox2d對(duì)象的起始坐標(biāo)在中心,而easel的起始坐標(biāo)在左上方。
既然我們可以把圖像添加到stage中了,現(xiàn)在就來看一下box2d的迷人之處吧。
box2d.createBird(birdBMP);
- var createBird = function(skin) {
- var birdFixture = new b2FixtureDef;
- birdFixture.density = 1;
- birdFixture.restitution = 0.6;
- birdFixture.shape = new b2CircleShape(24 / SCALE); // half of bird.png width divided by world scale for right size
- var birdBodyDef = new b2BodyDef;
- birdBodyDef.type = b2Body.b2_dynamicBody;
- birdBodyDef.position.x = skin.x / SCALE; // divide skin x and y by box2d scale to get right position
- birdBodyDef.position.y = skin.y / SCALE;
- var bird = world.CreateBody(birdBodyDef);
- bird.CreateFixture(birdFixture);
- bodies.push(bird);
- }
以上的代碼將會(huì)創(chuàng)建一個(gè)與鳥位圖對(duì)象具有相同大小和位置的圓形box2d body。但很可惜,鳥的皮膚沒有映射到box2d對(duì)象。如果不在調(diào)試狀態(tài)的話,你是看不到box2d的圓圈的,鳥也會(huì)保持靜止。這樣,我們?cè)趺茨茏屍つw隨著box2d body位置的改變而變化呢?
Actors! 在box2d的可視化示例中,Actors是必不可少的。在游戲中進(jìn)行循環(huán)時(shí)以及將box2d對(duì)象的米制位置轉(zhuǎn)換成像素位置時(shí),基本上都會(huì)運(yùn)行Actors。下面我們就來創(chuàng)建一個(gè)Actor。
- var actor = new actorObject(bird, skin);
- bird.SetUserData(actor); // set actor as userdata of body so we can get at it later if we need to
- var actorObject = function(body, skin) {
- this.body = body;
- this.skin = skin;
- this.update = function() { // translate box2d positions to pixels
- thisthis.skin.rotation = this.body.GetAngle() * (180 / Math.PI);
- thisthis.skin.x = this.body.GetWorldCenter().x * SCALE;
- thisthis.skin.y = this.body.GetWorldCenter().y * SCALE;
- }
- actors.push(this);
- } 這是最基本的actor對(duì)象的例子,當(dāng)然,你可以對(duì)它進(jìn)行任意擴(kuò)充。我們還需要告知actor在循環(huán)期間進(jìn)行更新。
- // within physics loop before world.step
- for(var i=0, l=actors.length; i<l; i++) {
- actors<i>.update();
- }
對(duì)于box2d body在物理模擬中所發(fā)生的一切變化,位圖皮膚都會(huì)對(duì)其進(jìn)行映射。
如果你想把某點(diǎn)上的body和其皮膚一并去除的話,可以將該body加入到“即將被去除的”數(shù)組中。在每次執(zhí)行world.step之前,這些bodies必須被去除掉。
- // before step
- for(var i=0, l=bodiesToRemove.length; i<l; i++) {
- removeActor(bodiesToRemove<i>.GetUserData()); // get the actor object in the user data of the body and send to removeActor function
- bodiesToRemove<i>.SetUserData(null);
- world.DestroyBody(bodiesToRemove<i>);
- }
- // after step
- if(bodies.length > 30) {
- bodiesToRemove.push(bodies[0]);
- bodies.splice(0,1);
- }
- var removeActor = function(actor) {
- stage.removeChild(actor.skin);
- actors.splice(actors.indexOf(actor),1);
- }
就是這些了。當(dāng)你理解諸如:命中次數(shù)、box2d 碰撞過慮器的改變、越界檢查等這樣的actors之后,可以實(shí)現(xiàn)更加強(qiáng)大的功能。我也希望在以后的指南中介紹更多這方面的知識(shí)。
原文鏈接:http://www.luxanimals.com/blog/article/combining_easel_box2d?utm_source=html5weekly&utm_medium=email
作者:Son Tran ,發(fā)表于2012年4月22日