2013-07-11 2 views
0

일부 컨텍스트 : C++ 및 Objective-C 하이브리드가 포함 된 Cocos2D/Box2D 용 2D Destructible 지형 라이브러리를 작성하고 있습니다. 최근 병렬 배열과 관련이없는 솔루션을 생각할 수없는 상황에 직면했습니다.Objective-C 및 C++로 병렬 배열 피하기

지형 주위에 물리 경계를 정의하려면 지형 경계의 초기 추적을해야합니다. 나는 텍스쳐 내 모든 격리 된 픽셀 몸체를 추적하고 캐쉬하기 위해 함수 호출을한다. 이는 키가 화소의 고유 위치와 동일한 인 NSValue에 싸서 CGPoint 이상임과 함께 다음 데이터 구조

  • NSMutableDictionary "borderPixels"를 생성한다. 추적 된 모든 픽셀을 유지합니다. TerPixels는 지형 본체의 '시작'지점을 나타내는 하나의 TerPixel을 보유하고 그들의 다음 이웃 픽셀
  • 있는 NSMutableArray "traceBodyPoints"를 가리키는
  • 원형 연결리스트. 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에서 Objective-C 컨테이너에 C++ 객체/포인터를 포함 할 수 없습니다. 문제는 이러한 작업이 믿을 수 없을 정도로 성능이 있어야하고 브리지 캐스팅에 참여하는 것이 매우 비용이 많이 든다는 것입니다. 또한 모든 단일 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 녹색 경계는 물리 경계입니다.

+0

당신은 Chipmunk Indie/Pro를 고려 했습니까? 파괴 가능한 지형에 자동 기하학이라는 기능이 내장되어 있습니다. http://www.youtube.com/watch?v=oacZwUGP11c – LearnCocos2D

+0

아니요. 들어 본 적이 없습니다. 나는 잠시 동안 Box2D Destructible Terrain 솔루션을 원했습니다. 나는 해결책으로 95 % 정도를 마쳤다. 그래서 나는 그것을 끝내는 것도 좋을 것 같다. 내가 만들고있는 라이브러리를 통해 사용자는 한 번의 호출로 여러 지형 충돌을 피하고 지형을 파괴하고 물리를 재정의 할 수 있습니다. 되돌아 보면 나는 내가 생각했던 것보다 더 많이 둘러 봐야했다. Btw, 너의 책을 읽어라. 좋은 읽을 거리! –

답변

2

다리 주조에 참여는

는 누가 그래

매우 비용이 많이 드는? 여전히 캐스트이며 본질적으로 자유롭고 무시할 만합니다. 브리지 전송 또는 유지 캐스트는 해당 참조 계산 방식 호출을 추가하지만 여기에서는 필요하지 않습니다.

문제의 해결 방법은 정말 간단합니다. TerPixel 클래스의 인스턴스를 포함하는 traceBodyPoints 배열이 있습니다.

이 배열에 대한 래퍼 클래스가 필요하면 TerrainBlob으로 전화를 걸면됩니다.TerrainBlob 클래스는 속성으로 포함 된 NSMutableArray를 traceBodyPoints과 b2Body의 또 다른 특성 : 당신은 사이클을 유지 피하기 위해 약한해야 TerrainBlob에 역 참조를 포함 할 TerPixel을 향상시킬 수

@interface TerrainBlob : NSObject 
@property NSMutableArray* traceBodyPoints; 
@property b2Body* body; 
@end 

. 그렇게하면 각 픽셀이 b2Body에 액세스 할 수 있습니다. 또한 TerPixel을 추가하고 편의상 terrainBlob 속성을 올바르게 설정하는 TerrainBlob 메서드를 추가 할 수 있습니다.

b2Body* body = _terrainBlob.body; 
if (body) 
{ 
    // do something with body 
} 

지금 당신은 단지 한 위치에서 몸을 업데이트해야하고, 각 TerPixel 사용하기 전에 몸이 nil 여부를 확인해야합니다 :

@interface TerPixel : NSObject 
... 
@property (weak) TerrainBlob* terrainBlob; 
@end 

그런 다음 TerPixel 내에서 b2Body에 액세스 할 수 있습니다 .

마지막으로, 픽셀 기반의 파괴적인 지형은 특히 망막 장치에 과도 함이라고 언급 할 가치가 있습니다. 이미 그렇게하지 않는 한 물리 시뮬레이션에서 픽셀 완벽 정확도가 실제로 필요하지 않기 때문에 여러 픽셀에 걸쳐있는 대략적인 선 모양을 만드는 방법을 살펴보십시오.

+1

답장을 보내 주셔서 감사합니다. 나는 실제로 그것들을 평균화하고 곡률을 조정함으로써 꼭지점을 부드럽게 만듭니다. 나는 관련성이 없다고 생각하면서 여기 정보를 전달하지 않았다. 따라서 600 개의 꼭지점 배열은 객체가 어떻게 구부러지는 지에 따라 20-40 정도가됩니다. 작업 후이 솔루션에 대해 더 자세히 살펴 보겠습니다. –

+0

감사합니다. Steffen. 이것은 정말로 잘 돌아갔다. –

+0

차가움. 이 자료를 상업적으로 또는 무료로 공개한다면 알려주십시오. – LearnCocos2D