Egret-Box2d (一)
按照官方文檔學(xué)習(xí)的記錄,由于文檔是英文的,所以本文中的截圖都是經(jīng)過百度翻譯過的,box2d github地址:https://github.com/flyover/box2d.ts

首先要創(chuàng)建一個放置物體的地方,也就是box2dWorld,簡稱為b2World,其中x和y就是重力的大小和方向了,y:10也就是重力加速度。
?this.world?=?new?b2World({?x:?0,?y:?10?});
有了世界還需要有地面,這里就涉及到單位轉(zhuǎn)換了,box2d使用的是MKS單位,也就是米、千克、秒,并不是我們常用的px(像素),由百度可知,1 米=30 像素。
let?groundBodyDef?=?new?b2BodyDef();
groundBodyDef.position.Set(0,?300?/?30);//此處就是把300像素轉(zhuǎn)換成10米
groundBodyDef.type?=?b2BodyType.b2_staticBody;//地面是不會動的,所以設(shè)置為靜態(tài)的
上面的只是對物體進行定義,然后開始創(chuàng)建一個物體
?let?groundBody?=?this.world.CreateBody(groundBodyDef);
接下來是對物體的形狀進行設(shè)置
?let?groundBox?=?new?b2PolygonShape();//這是個矩形
?groundBox.SetAsBox(500?/?2?/?30,?30?/?2?/?30);
//這里有個500?/?2?/?30,是不是感覺很詭異?
根據(jù)官方文檔解釋,SetAsBox的參數(shù)是半寬半高,所以要除以2,后面的除以30是單位轉(zhuǎn)換

然后給物體添加上這個形狀,后面的1是這個物體的密度,因為物體都是有密度的,所以不寫的話可能會出現(xiàn)奇怪的bug,這個方法還有其他的重載,所以密度寫在其他地方也可以
groundBody.CreateFixture(groundBox,?1);
然后地面就創(chuàng)建好了,不過運行起來還是什么都看不到的,因為box2d不自帶渲染,然后我也找不到合適的b2debugdraw,我也不想自己寫,就先用egret做個矩形吧
let?rect?=?new?egret.Sprite();
rect.graphics.beginFill(Math.random()?*?0xffffff);
rect.graphics.drawRect(0, 0,?500,?30);
rect.graphics.endFill();
rect.anchorOffsetX?=?500?/?2;
rect.anchorOffsetY?=?30?/?2;
rect.x=0;
rect.y=300;
groundBodyDef.userData?=?rect;//這里的userData用于存一些東西
this.addChild(rect);
然后運行起來就能發(fā)現(xiàn)創(chuàng)建的地面了

然后我們來創(chuàng)建一個牛頓的蘋果,還是上面的操作,只是把靜態(tài)改成動態(tài)了。
let?appleDef?=?new?b2BodyDef();
appleDef.type?=?b2BodyType.b2_dynamicBody;//動態(tài)的
appleDef.position.Set(30?/?30,?30?/?30);
因為蘋果可以受到力的影響,所以要給他添加一下材質(zhì)(也叫夾具),就是密度、摩擦、形狀等。
let?fixDef?=?new?b2FixtureDef();//這個就是材質(zhì)
let?appleShape?=?new?b2PolygonShape();
appleShape.SetAsBox(50?/?2?/?30,?50?/?2?/?30);
fixDef.shape?=?appleShape;
fixDef.density?=?1.0;//這個就是之前提到過的密度
fixDef.friction?=?0.3;//這個是摩擦
fixDef.restitution?=?0.2;//掉在地上彈起來的效果
this.world.CreateBody(appleDef).CreateFixture(fixDef);//添加到世界中
然后為了方便實用,把之前那個創(chuàng)建矩形(egret的那個)封裝一下
createRect(x,?y,?width,?height)?{
????????let?rect?=?new?egret.Sprite();
????????rect.graphics.beginFill(Math.random()?*?0xffffff);
????????rect.graphics.drawRect(0,?0,?width,?height);
????????rect.graphics.endFill();
????????rect.anchorOffsetX?=?width?/?2;
????????rect.anchorOffsetY?=?height?/?2;
????????rect.x?=?x;
????????rect.y?=?y;
????????return?rect;
????}
然后讓蘋果顯示出來
appleDef.userData?=?this.createRect(30,?30,?50,?50);
this.addChild(appleDef.userData);
這是我們運行一下,會發(fā)現(xiàn)蘋果是掉不下來的,因為我們還沒有把box2d啟動起來
//在合適的地方添加監(jiān)聽
this.addEventListener(egret.Event.ENTER_FRAME,?this.loop,?this);
//每幀調(diào)用這個方法
loop()?{
????????this.world.Step(1?/?60,?6,?2);
????????for?(var?bodyIndex:?b2Body?=?this.world.GetBodyList();?bodyIndex;?bodyIndex?=?bodyIndex.GetNext())?{
????????????if?(bodyIndex.m_userData?!=?null)?{
????????????????bodyIndex.m_userData.x?=?bodyIndex.GetPosition().x?*?30
????????????????bodyIndex.m_userData.y?=?bodyIndex.GetPosition().y?*?30
????????????????bodyIndex.m_userData.rotation?=?bodyIndex.GetAngle()?*?180?/?Math.PI;
????????????}
????????}
????}
上面的Step中的第一個參數(shù)是時間步長,1 / 60相當(dāng)于六十分之一秒執(zhí)行一次,也就是60hz,后邊那兩個參數(shù)為什么寫6和2,就看官網(wǎng)的解釋吧。

后面的for循環(huán)就是遍歷每一個物體,并改變他的位置和角度,注意box2d用的是弧度制,不是角度值,而且還要進行單位的轉(zhuǎn)換。
效果圖

還可以添加多個


box2d 文檔地址:https://box2d.org/documentation/md__d_1__git_hub_box2d_docs_hello.html