4

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);      
}

それは単にボールからのタッチポイントの距離を計算し、距離に応じてボールに適用する力を見つけ、ボールをタッチした方向に動かすことです. そして、このボールは、邪魔になる他のボールと衝突します。

4

2 に答える 2

5

ダフィーモの答えをさらに詳しく説明しましょう。

CCLayer のtickメソッドに次のコードが含まれていることを覚えていますか?:

int32 velocityIterations = 8;
int32 positionIterations = 1;

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

2 つの int32 変数は、box2D に、力を加えたり、衝突を検出したりするために何回の反復 (つまり、パス) を行う必要があるかを伝えます。box2D のマニュアルによると、これらの値を大きくすると、パフォーマンスを犠牲にしてシミュレーションの精度が向上し、これらを小さくするとその逆になります。値。したがって、結果に満足するまで、これらの値、特に positionIterations を微調整することをお勧めします。

編集:

ここに別の提案があります。tickメソッドが fps と同じレート (最大で 1 秒あたり 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
}
于 2011-03-22T16:40:44.560 に答える
0

侵入検出を改善する必要があります。空間または時間、あるいはその両方で感度を上げます。

于 2011-03-19T13:28:21.693 に答える