1、創建一個物理世界
首先要引入一個頭文件#include "Box2D\Box2D.h"
之後利用b2word創建一個對象,並且指定這個物理世界中的加速度方向。
word = new b2World(b2Vec2(0,-10)); //指定物理世界的加速度
最後還要重寫一下update函數,這個函數在之前的計時器學習的時候已經說過,每一幀的變動都將自動執行這個函數。所以我們要通過這個函數來進行創建的物理世界的刷新。
2、創建一個運動的物體
我們將自己實現一個在物理世界添加一個物體的函數,在其中調用createbody來創建一個物體,該函數接受一個參數。這個參數是關於創建的這個物體的一些基本信息,比如位置,動態還是靜態等等。
b2BodyDef def;
def.position = b2Vec2(10,10);
def.type = b2_dynamicBody;
word->CreateBody(&def);
之後爲了能夠顯示出創建的這個物體的運動情況,在update中,可以通過一個循環來便利整個物理世界的物體列表,找到我們定義的這個物體就可以輸出他在物理世界中自由落體的座標變化
void HelloWorld::update(float dt)
{
word->Step(dt, 8, 3);
for(b2Body *b = word->GetBodyList(); b; b = b->GetNext())
{
if(b->GetType() == b2_dynamicBody)
{
log("x:%f, y:%f", b->GetPosition().x, b->GetPosition().y);
}
}
}
最後要在init函數裏面scheduleUpdate()用這個函數啓動update
直接看座標的變化可能不是很明顯,那麼這次通過添加一個圖形來看
首先,自然要先創建一個sprite。
然後將創建的那個物體和sprite綁定在一起。
b2Body *b = word->CreateBody(&def);
auto sprite = Sprite::create();
addChild(sprite);
sprite->setTextureRect(Rect(0,0,80,80));
b->SetUserData(sprite);
因爲BOX2d 物理世界中,它的位置是用米來進行度量的,並不是利用像素。BOX2D有一個比較精確的模擬範圍就是10M。所以我們要根據像素和米的單位進行映射,找出對應的比例關係才能夠確定所創建物體要指定的位置。
所以,在AppDelegate::applicationDidFinishLaunching()函數中我們將設置一下程序的分辨率glview->setDesignResolutionSize(800,600, ResolutionPolicy::SHOW_ALL);設置了一個800*600的分辨率,也就是說縱軸的800對應於物理世界中的10m,那麼他們的比例就是80。
也就是說,上述的操作形成了這樣的一個效果,把整個屏幕變成了800*600的分辨率,在物理世界中,最高的縱座標範圍是10.按照比例縮小的座標系的範圍。
創建的物體在物理世界中的位置可以通過def.position = b2Vec2(3,5);來進行指定,def是這個物體類型信息的一個對象。但是如果要連接一個圖形的話,那麼圖形不是物理世界中,它是cocos2dx裏面得東西,是遊戲引擎的部分,所以,要通過剛纔的比例設置sprite的位置。
s->setPosition(b->GetPosition().x * RATIO, b->GetPosition().y*RATIO);
s是一個sprite的指針。
上面的工作雖然將物理世界得物體和圖形進行了綁定,但是,這只是靜態的東西。所創建的物體在物理世界中是會因爲重力的原因下落的,那麼與其綁定的圖形也就要隨之調整位置,所以在Update函數裏面要實時更新圖形的位置。
void HelloWorld::update(float dt)
{
word->Step(dt, 8, 3);
Sprite *s;
for(b2Body *b = word->GetBodyList(); b; b = b->GetNext())
{
if(b->GetType() == b2_dynamicBody)
{
if(b->GetUserData())
{
s = (Sprite*)b->GetUserData();
s->setPosition(b->GetPosition().x * RATIO, b->GetPosition().y*RATIO);
}
}
}
}
所以在update函數裏面就要檢查body對象是否綁定了圖形,然後獲取到他所綁定的圖形,進行重新設置當前的圖形座標。