Box2d中剛體的紋理的幾種實現方式
Box2d中建立完剛體並將裝置(fixture)附加到剛體上以後,還需要對剛體應用紋理才能夠讓剛體看起來像一個真正的物體,而不是一個個多邊形或者圓形線框。因此,總結了下面幾種為剛體新增紋理的思路。
1.最簡單的方式就是使用CCPhysicsSprite類,CCPhysicsSprite是cocos2d 2.1之後引入的,支援Chipmunk和Box2d兩個框架,類中定義了b2Body成員用來儲存其對應的剛體,該類重寫了nodeToParentTransform,position和rotation的get/set等方法,獲取對應剛體的座標和轉角,然後使用座標和轉角來更新其紋理的位置和旋轉,從而使紋理和剛體能夠同步移動和旋轉。
使用CCPhysicsSprite的方式很簡單:
CCPhysicsSprite*sprite = [CCPhysicsSprite spriteWithTexture:texture rect:CGRectMake(x, y,width, height)];
[parentaddChild:sprite];
[spritesetPTMRatio:PTM_RATIO];
[spritesetB2Body:body];
[spritesetPosition: ccp( p.x, p.y)];
首先通過初始化方法初始化紋理texture和紋理的繪製區域(矩形區域),接著將該精靈物件新增到場景中(與一般的CCSprite物件用法相同),接著設定單位轉換的比例(Box2d中的“米”與畫素之間的轉換比例,即PTM_RATIO),然後指定對應的剛體(body),最後設定其初始的位置即可。
不需要做額外的操作,精靈的紋理便會隨著剛體的運動而運動。
有興趣的朋友可以在cocos2d類庫中找到CCPhysicsSprite.h和CCPhysicsSprite.mm檔案看一下具體的實現方法。
2.上面第一種方式,我們使用了cocos2d中為我們提供的類庫來實現剛體和紋理的同步運動。同樣,我們也可以自己定義一個類(暫且就叫它MyB2Body),MyB2Body中包含CCSPrite和b2Body這兩個成員(除了這兩個成員,其它成員根據需求而定,不在我們的討論範圍內),然後在MyB2Body中定義自己的更新方法(就叫updateBodyAndSprite吧),接著在我們需要更新剛體位置的地方呼叫
這種方式和第一種方式的區別在於,它為我們提供了更多的靈活性,當然你也可以說,因為cocos2d是開源的,所以我們也可以修改CCPhysicsSprite類,所以其同樣具有靈活性,但是如果我們修改CCPhysicsSprite類,則會影響到你機器上其他使用cocos2d框架的應用程式。而且這裡我們並不是重寫position或者rotation的get/set方法,而是實現自定義的方法供手動呼叫。
具體的例子可以看一下另一篇博文手把手教你製作一款Box2D小遊戲(一)中StepBlock類的實現(該類中使用CCPhysicsSprite,其實使用CCSprite即可滿足需求)。
3.上面兩種方法我們通過定義類或者使用庫中定義的類來完成,實際上,b2Body物件為我們提供了一個很好的屬性來儲存其對應的精靈,即userData這個屬性。b2Body的userData屬性用來存放任何我們想存放的資料,那麼我們乾脆就在userData中存放其對應的精靈物件就好了(這裡說是存放,其實是userData指向剛體對應的精靈物件)。PhysicsEditor附帶的例子中實際上就用的是這種方法。在update方法中,首先通過world->Step(dt,velocityIterations, positionIterations)來計算並更新所有剛體的位置,接著通過下面的迴圈來更新所有剛體對應的精靈的紋理:
for(b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL)
{
CCSprite *myActor = (CCSprite*)b->GetUserData();
myActor.position = CGPointMake(
b->GetPosition().x* PTM_RATIO, b->GetPosition().y * PTM_RATIO);
myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
這種方式與我們第二種方式有些類似,都需要在其他方法中手動更新精靈的位置。
好了,以上就是關於剛體紋理的一點點心得,如果有說的不清楚的地方,歡迎留言指正~