具有碰撞检测的多点触控精灵旋转

时间:2013-02-01 14:49:24

标签: ios objective-c cocos2d-iphone box2d

我正在尝试实现碰撞检测和基于物理的一个精灵的反弹,这个反射是由多点触控旋转的另一个精灵。在图像中,看到两个黄点是同时触摸点,我根据ccTouchesBegan方法中的那些触摸以及ccTouchesMoved方法计算了云的正确位置和角度。当用户移动并旋转两个触摸时,云跟随并相应地旋转。

enter image description here

我尝试将云的角度传递给另一种方法,当鸟类使用CGRectIntersectsRect与云相撞并使用数学滚动我自己的碰撞/弹跳时,但是这并没有产生预期的结果所以我转过身来到Box2D。

经过Ray Wenderlich教程的4或5后,我无法将我用多点触控云创建的机芯与机身,灯具,鼠标和Box2D的世界进行网格划分。

我读过这个:Cocos2d - Collision Detection of Rotated Sprite

......已经完成了这个: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代码时,云只响应第一次触摸,不会调整到触摸之间创建的角度不遵循两个接触。我怎样才能用Box2D实现这个目标?

有人有任何建议吗?

1 个答案:

答案 0 :(得分:0)

可爱的艺术品!

您需要为多点触控体提供速度和位置信息,以便与其他与之相互作用的物体获得适当的碰撞响应。

运动体实际上非常适合此目的。您所做的是设置云的几何形状,当多点触控位置更新时,您可以计算将云从当前位置移动到由触摸定义的新目标位置所需的线性和角速度。这就是你移动运动体(速度)的方法。你可以使它轻轻地漂移或严格地跟随运动 - 运动体,它会严格碰撞,不会因碰撞而产生任何动量。

你还需要弄清楚如何处理这样一个事实,即运动体的实际长度可以随着手指移动而改变。

希望有所帮助