2011-03-19 37 views
4

我知道Box2d世界中的快速移動物體會導致隧道效應並相互穿越。解決方案是將物體定義爲子彈。我做到了,但是有時候身體仍然互相交叉,特別是如果相遇點不完全朝向中間,身體部分重疊而過境。任何解決方案Box2d中的快速移動物體有時會互相穿過

這是我想提出的所有機構:

redBall = [CCSprite spriteWithFile:@"red-ball" rect:CGRectMake(0, 0, 34, 34)]; 
redBall.tag = 1; 
[self addChild:redBall]; 
ballBodyDef.type = b2_dynamicBody; 
ballBodyDef.position.Set((winSize.width/2)/PTM_RATIO, redBall.position.y/PTM_RATIO); 
ballBodyDef.userData = redBall; 

ballBodyDef.bullet = true; 
_ballBody = _world->CreateBody(&ballBodyDef); 

// Create circle shape 
b2CircleShape circle; 
circle.m_radius = 17.0/PTM_RATIO; 

// Create shape definition and add to body 
b2FixtureDef ballShapeDef; 
ballShapeDef.shape = &circle; 
ballShapeDef.density = 0.2f; 
ballShapeDef.friction = 0.0f; 
ballShapeDef.restitution = 1.0f; 
_ballFixture = _ballBody->CreateFixture(&ballShapeDef); 

我在TouchesEnd移動這個球爲:

- (void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 

    UITouch *myTouch = [touches anyObject]; 
    CGPoint location = [myTouch locationInView:[myTouch view]]; 
    location = [[CCDirector sharedDirector] convertToGL:location];   

    CGPoint shootVector = ccpSub(location, striker.position); 
    CGFloat shootAngle = ccpToAngle(shootVector); 
    CGPoint normalizeShootVector = ccpNormalize(shootVector); 

    float x1 = - cos(shootAngle); 
    float y1 = - sin(shootAngle); 

    int power = 0; 
    float dist =ccpDistance(location, redBall.position); 
    if (dist >= 200) 
     power = 20; 
    else if (dist >= 100) 
     power = 10; 
    else if (dist >=75) 
     power = 7; 
    else if (dist >= 60) 
     power = 4; 
    else if (dist >= 50) 
     power = 3; 
    else if (dist >= 35) 
     power = 2; 
    else 
     power = 1; 

    b2Vec2 force = b2Vec2(x1*power, y1*power); 
    _ballBody->ApplyLinearImpulse(force,ballBodyDef.position);  
} 

它只是觸摸點的距離計算起球,根據距離尋找適用於球的力量並在觸摸方向上移動球。這個球與任何其他進球的球碰撞。

+0

可能的代碼將有助於我們 – BlackBear 2011-03-19 13:21:03

+0

我已經添加了相關的代碼。 – WaJiyaz 2011-03-19 14:03:03

回答

5

讓我詳細闡述duffymo的答案。

記住CCLayer的tick方法包含以下代碼?:

int32 velocityIterations = 8; 
int32 positionIterations = 1; 

world->Step(dt, velocityIterations, positionIterations); 

兩個INT32變量告訴Box2D的多少次迭代(即通過)它應該做的施加力,檢測碰撞等。根據box2D manual,增加這些值會以性能爲代價提高仿真精度,反之亦然,從而降低這些值。所以我建議你調整這些值,尤其是positionIterations,直到你對結果滿意爲止。

編輯:

這裏是另一個建議。再次記住,tick方法的調用速度與fps相同,每秒最多60個?這意味着b2World::Step函數以1/60秒的間隔進行離散模擬,所以如果一個快速運動的物體花費的時間少於這個時間量,它就可以通過另一個物體。所以要解決這個問題,你需要增加離散模擬的頻率,比方說每秒180步。但問題是如何? Cocos2D-iPhone爲每一幀調用tick方法,並增加幀率(如果甚至可能的話)會降低性能並浪費所有的處理能力。

這裏是你如何能做到這一點不改變幀率,通過調用函數b2World::Step相同刻度之內幾次:

int32 velocityIterations = 8; 
int32 positionIterations = 1; 
uint substeps = 3; 
float32 subdt = dt/substeps; 

for (uint i = 0; i < substeps; i++) { 
    world->Step(subdt, velocityIterations, positionIterations); 

    // do your physics-related stuff inside here but leave any sprites manipulation outside this loop 
} 
+0

謝謝,但我已經嘗試過使用這些值。最初他們分別是10和1。我也嘗試過20,20。在應用線性脈衝之前,我也嘗試從速度矢量中調整速度。但沒有顯着的成功。而這種傳遞行爲只是偶爾發生,並非一直髮生。 – WaJiyaz 2011-03-22 22:11:12

+0

@WJK:我用另一個建議更新了答案 – Lukman 2011-03-23 03:07:35

+0

它的確增加了碰撞的靈敏度,但起初所有的屍體開始瘋狂地移動。我嘗試了子步驟= 2,各種滴答間隔以及增加物體密度的平衡運動,但無法達到理想的結果。此外,它影響所有其他定時器和循環控制。 – WaJiyaz 2011-03-23 13:45:31

0

您需要優化穿透檢測:增加空間或時間或兩者的靈敏度。