某些上下文:我正在爲Cocos2D/Box2D編寫一個2D可破壞地形庫,它涉及C++和Objective-C的混合。我最近遇到了一個讓我難以想象不涉及平行陣列的解決方案的局面。使用Objective-C和C++避免平行數組
爲了在地形周圍定義物理邊界,必須首先對地形邊界進行跟蹤。我做了一個函數調用來跟蹤紋理中所有孤立像素體並緩存它們。這產生與密鑰等於包裹在一個NSValue一個CGPoint其是等於像素的獨特位置處的以下數據結構
- 一個NSMutableDictionary「borderPixels」。這包含所有跟蹤的像素。
- 一個圓形鏈表與TerPixels指向他們的下一個鄰居像素
- 一個NSMutableArray「traceBodyPoints」,它包含一個表示地形體的'開始'點的單個TerPixel。我只在這裏存儲TerPixel *,我需要跟蹤一個物理機構。因此,如果地形主體已被修改,我將修改過的主體中的任何單個TerPixel *插入到該陣列中。然後我可以引用每個這些並遍歷鏈表來追蹤物理體。
下面是一些代碼,以幫助塗料的情況更好的畫面:
-(void)traverseBoundaryPoints:(CGPoint)startPt {
if (!borderPixels) borderPixels = [[NSMutableDictionary alloc] init]; // Temp
if (!traceBodyPoints) traceBodyPoints = [[NSMutableArray alloc] init]; // Temp
TerPixel * start = [[TerPixel alloc] initWithCoords:startPt.x ypt:startPt.y prevx:-1 prevy:0];
TerPixel * next = start;
//CCLOG(@"Start of traverseBoundary next.x and next.y %d, %d", next.x, next.y);
TerPixel * old;
while (true) {
old = next;
next = [self findNextBoundaryPixel:next];
[next setNSP:[old subTerPixel:next]];
old.nextBorderPixel = next;
if (next.x == start.x && next.y == start.y) {
CCLOG(@"SUCCESS :: start = next");
next.nextBorderPixel = start; // Make the linked list circular
NSValue * pixLocVal = [next getAsValueWithPoint];
[borderPixels setObject:next forKey:pixLocVal];
// Add the pixel to the tracePoints array to be traversed/traced later
[traceBodyPoints addObject:start];
break;
} // end if
// Connect the linked list components
NSValue * pixLocVal = [next getAsValueWithPoint];
[borderPixels setObject:next forKey:pixLocVal];
} // end while
} // end traverse function
這裏就是我無法找到一個解決方案。我需要將traceBodyPoints數組中的每個TerPixel *與將創建並添加到物理世界的Box2D b2Body關聯起來。在我的庫中,紋理中每個孤立的像素體對應於Box2D主體。所以,當一個事件發生,破壞了一塊地形,我需要摧毀與被破壞的像素相關聯的物體,並且僅回顧這些被改變的物體。這意味着我需要一種方法將任何給定的TerPixel *關聯到Box2D主體*。
在使用ARC的Objective-C中,就我所知,我無法在C++容器中包含C++對象/指針而無需將橋接器強制轉換爲void *。問題是這些操作需要令人難以置信的高性能,參與橋樑鑄造的成本非常高。另外,我不想在每個TerPixel中包含指向Box2D主體的指針。這將是一場噩夢,以確保沒有懸掛指針,並且需要無意義的迭代來消除指針。
這裏是我創建的物理邊界
-(void)createPhysicsBoundaries {
if ([self->traceBodyPoints count] == 0) {
CCLOG(@"createPhysicsBoundaries-> No bodies to trace");
return;
}
// NEED LOGIC HERE TO DELETE ALTERED BODIES
// NEED TO DELETE EXISTING BOX2D BODY AND RE-TRACE A NEW ONE
// For each body that has been altered, traverse linked list to trace the body
for (TerPixel * startPixel in self->traceBodyPoints) {
TerPixel * tracePixel = startPixel.nextBorderPixel;
b2BodyDef tDef;
tDef.position.Set(0, 0);
b2Body * b = self->world->CreateBody(&tDef);
self->groundBodies->push_back(b);
b->SetUserData((__bridge void*) self);
b2EdgeShape edgeShape;
CCLOG(@"StartPixel %d, %d", startPixel.x, startPixel.y);
while (tracePixel != startPixel) {
b2Vec2 start = b2Vec2(tracePixel.x/PTM_RATIO, tracePixel.y/PTM_RATIO);
//CCLOG(@"TracePixel BEFORE %d, %d", tracePixel.x, tracePixel.y);
tracePixel = tracePixel.nextBorderPixel;
//CCLOG(@"TracePixel AFTER %d, %d", tracePixel.x, tracePixel.y);
b2Vec2 end = b2Vec2(tracePixel.x/PTM_RATIO, tracePixel.y/PTM_RATIO);
edgeShape.Set(start,end);
b->CreateFixture(&edgeShape, 0);
} // end while
} // end for
} // end createPhysicsBoundaries
希望這是有道理的邏輯。如果您需要了解正在發生的事情,請看這裏的視頻。 http://www.youtube.com/watch?v=IUsgjYLr6e0&feature=youtu.be綠色邊界是物理邊界。
你有沒有考慮過Chipmunk Indie/Pro?它有一個稱爲內置可破壞地形的自動幾何特徵。 http://www.youtube.com/watch?v=oacZwUGP11c – LearnCocos2D
不,我從來沒有聽說過它。我一直想要一個Box2D可破壞地形解決方案。我大約有95%完成了解決方案...所以我想我可以完成它。我正在建造的圖書館允許用戶通過一次呼叫和經理多體碰撞來對待地形的破壞和物理重新定義。回想起來,我應該更多地環顧四周。順便說一句,讀你的書。很棒的閱讀! –