0

衝突検出と、マルチタッチによって回転した別のスプライトからの 1 つのスプライトの物理ベースのバウンスを実装しようとしています。ccTouchesBegan画像では、2 つの黄色い点が同時タッチ ポイントであることがわかります。メソッドとメソッドで、これらのタッチに基づいて雲の適切な位置と角度を計算しましたccTouchesMoved。ユーザーが 2 つのタッチを移動および回転すると、それに応じて雲が追従し、回転します。

ここに画像の説明を入力

鳥が雲に衝突したとき、独自の種類の衝突/跳ね返りを数学で使用して転がすときに、雲の角度を別の方法に渡そうとしましたCGRectIntersectsRectが、これでは望ましい結果が得られなかったため、Box2D に目を向けました。

Ray Wenderlich のチュートリアルを 4 つまたは 5 つ実行した後、マルチタッチ クラウドで作成した動きを、Box2D のボディ、フィクスチャ、マウス ジョイント、およびワールドとメッシュ化するのに問題があります。

私はこれを読みました: Cocos2d - 回転スプライトの衝突検出

...そして、すでにこれを行っています: Ray Wenderlich Collision Detection

私の最新のccTouchesMoved方法は次のようになります。

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

    if (_mouseJoint != NULL) return;

    UITouch *myTouch = [touches anyObject];
    CGPoint location = [myTouch locationInView:[myTouch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];
    b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);


    if (_cloudFixture->TestPoint(locationWorld)) {
        b2MouseJointDef md;
        md.bodyA = _groundBody;
        md.bodyB = _cloudBody;
        md.target = locationWorld;
        md.collideConnected = true;
        md.maxForce = 1000.0f * _cloudBody->GetMass();

        _mouseJoint = (b2MouseJoint *)_world->CreateJoint(&md);
        _cloudBody->SetAwake(true);
    }

    NSSet *allTouches = [event allTouches];
    if([allTouches count] == 2){
        UITouch * touch1 = [[allTouches allObjects] objectAtIndex:0];
        CGPoint location1 = [touch1 locationInView: [touch1 view]];
        location1 = [[CCDirector sharedDirector] convertToGL:location1];

        UITouch * touch2 = [[allTouches allObjects] objectAtIndex:1];
        CGPoint location2 = [touch2 locationInView: [touch2 view]];
        location2 = [[CCDirector sharedDirector] convertToGL:location2];

        //EASIER TO WORK WITH INTS
        int touch1X = location1.x;
        int touch2X = location2.x;

        int touch1Y = location1.y;
        int touch2Y = location2.y;

        //FIND THE LEFT-MOST TOUCH
        int minX = (touch1X < touch2X) ? touch1X : touch2X;
        int maxX = (minX == touch1X) ? touch2X : touch1X;

        //FIND THE BOTTOM-MOST TOUCH
        int minY = (touch1Y < touch2Y) ? touch1Y : touch2Y;
        int maxY = (minY == touch1Y) ? touch2Y : touch1Y;

        int touchXDiff = maxX - minX;
        int touchYDiff = maxY - minY;

        [_cloud setPosition:ccp(touchXDiff/2 + minX, touchYDiff/2 + minY)];

        //ROTATE CLOUD AS IT MOVES

        int offDiffX = touch1X - touch2X;
        int offDiffY = touch1Y - touch2Y;

        float angleRadians = atanf((float)offDiffY / (float)offDiffX);
        float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
        float cloudAngle = -1 * angleDegrees;

        //[_cloud setRotation:cloudAngle];
        _cloudBody->SetTransform( _cloudBody->GetPosition(), cloudAngle );
    }

}

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

    if (_mouseJoint == NULL) return;

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

    NSSet *allTouches = [event allTouches];
    if([allTouches count] == 2){
        UITouch * touch1 = [[allTouches allObjects] objectAtIndex:0];
        CGPoint location1 = [touch1 locationInView: [touch1 view]];
        location1 = [[CCDirector sharedDirector] convertToGL:location1];

        UITouch * touch2 = [[allTouches allObjects] objectAtIndex:1];
        CGPoint location2 = [touch2 locationInView: [touch2 view]];
        location2 = [[CCDirector sharedDirector] convertToGL:location2];

        //EASIER TO WORK WITH INTS
        int touch1X = location1.x;
        int touch2X = location2.x;

        int touch1Y = location1.y;
        int touch2Y = location2.y;

        //FIND THE LEFT-MOST TOUCH
        int minX = (touch1X < touch2X) ? touch1X : touch2X;
        int maxX = (minX == touch1X) ? touch2X : touch1X;

        //FIND THE BOTTOM-MOST TOUCH
        int minY = (touch1Y < touch2Y) ? touch1Y : touch2Y;
        int maxY = (minY == touch1Y) ? touch2Y : touch1Y;

        int touchXDiff = maxX - minX;
        int touchYDiff = maxY - minY;


        //ROTATE CLOUD AS IT MOVES

        int offDiffX = touch1X - touch2X;
        int offDiffY = touch1Y - touch2Y;

        float angleRadians = atanf((float)offDiffY / (float)offDiffX);
        float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
        float cloudAngle = -1 * angleDegrees;

        //BEFORE BOX2D
        //[_cloud setRotation:cloudAngle];
        //[_cloud setPosition:ccp(touchXDiff/2 + minX, touchYDiff/2 + minY)];

        //WITH BOX2D
        _cloudBody->SetTransform( _cloudBody->GetPosition(), cloudAngle );
        b2Vec2 locationWorld = b2Vec2((touchXDiff/2 + minX)/PTM_RATIO, (touchYDiff/2 + minY)/PTM_RATIO);
        _mouseJoint->SetTarget(locationWorld);
    }

}

編集(わかりやすくするため): 何が起こっているかというと、Box2D コードが実装されている場合、クラウドは最初のタッチにのみ応答し、タッチ間に作成された角度に調整されず、2 つのタッチに追従しません。Box2D でこれを達成するにはどうすればよいですか?

誰か提案はありますか?

4

1 に答える 1

0

かわいいアートワーク!

マルチタッチ ボディに速度と位置の情報を吹き込み、他のボディと相互作用することで適切な衝突応答が得られるようにする必要があります。

実際、キネマティック ボディはこの目的に完全に適しています。クラウドのジオメトリを設定し、マルチタッチ位置が更新されると、クラウドを現在の位置からタッチによって定義された新しいターゲット位置に移動するために必要な線形速度と角速度を計算します。これは、キネマティック ボディを (速度で) 動かす方法です。動きに合わせて緩やかにドリフトさせたり、しっかりと追従させたりすることができます。キネマティック ボディを使用すると、しっかりと衝突し、衝突による運動量がそれ自体に与えられることはありません。

また、キネマティック ボディの実際の長さが指の動きに応じて変化する可能性があるという事実に対処する方法を理解する必要があります。

それが役立つことを願っています

于 2013-02-02T15:52:46.440 に答える