简体   繁体   English

具有碰撞检测功能的Multitouch Sprite旋转

[英]Multitouch Sprite Rotation with Collision Detection

I'm trying to implement collision detection and a physics-based bounce of one sprite off of another sprite rotated by multitouch. 我正在尝试实现碰撞检测以及将一个精灵从多点触摸旋转的另一个精灵中基于物理的反弹。 In the image, see that the two yellow dots are the simultaneous touch points and I've calculated the proper position and angle for the cloud based on those touches in the ccTouchesBegan method as well as the ccTouchesMoved method. 在图像中,看到的是,两个黄色的点是同时的触摸点,我已经计算出基于在这些触摸云中的适当的位置和角度ccTouchesBegan方法以及该ccTouchesMoved方法。 As the user moves and rotates the two touches the cloud follows and rotates accordingly. 当用户移动并旋转两次触摸时,云随之跟随并旋转。

在此处输入图片说明

I attempted to pass the angle of the cloud to another method when bird collided with the cloud using CGRectIntersectsRect and rolling my own sort of collision/bounce with math, but this did not produce the desired results so I turned to Box2D. 当小鸟使用CGRectIntersectsRect与云碰撞并用数学滚动我自己的碰撞/反弹时,我试图将云的角度传递给另一种方法,但这没有产生理想的结果,所以我转向Box2D。

After going through 4 or 5 of Ray Wenderlich's tutorials, I'm having trouble meshing the movement I created with the multi-touch cloud with the bodies, fixtures, mouseJoints, and worlds of Box2D. 在遍历了Ray Wenderlich的教程的4或5之后,我无法将使用多点触控云创建的运动与实体,固定装置,mouseJoint和Box2D的世界相结合。

I've read this: Cocos2d - Collision Detection of Rotated Sprite 我读过这篇文章: Cocos2d-旋转Sprite的碰撞检测

...and already gone through this: Ray Wenderlich Collision Detection ...并且已经经历过: Ray Wenderlich碰撞检测

My latest ccTouchesMoved method looks like this: 我最新的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);
    }

}

EDIT (for clarity): What is happening, is that when the Box2D code is implemented, the cloud only responds to the first touch, does not adjust to the angle created between the touches and does not follow the two touches. 编辑 (为清楚起见):发生的情况是,在实施Box2D代码时,云仅对第一次触摸做出响应,不适应两次触摸之间创建的角度,并且不跟随两次触摸。 How can I accomplish this with Box2D? 如何使用Box2D完成此操作?

Does anyone have any suggestions? 有没有人有什么建议?

Cute artwork! 可爱的艺术品!

You'll want to imbue your multitouch body with velocity and position information so as to get a proper collision response from other bodies interacting with it. 您将要向多点触摸身体施加速度和位置信息,以便从与其交互的其他身体获得适当的碰撞响应。

The kinematic body is actually perfectly suited for this purpose. 运动机构实际上非常适合此目的。 What you do is set the geometry of the cloud and as multitouch positions update, you compute the linear and angular velocities required to move the cloud from its current position to a new target position defined by the touches. 您要做的就是设置云的几何形状,并在多点触摸位置更新时,计算将云从其当前位置移动到由触摸定义的新目标位置所需的线速度和角速度。 This is how you move a kinematic body (with velocities). 这就是移动运动物体(具有速度)的方式。 You'll be able to make it gently drift or rigidly follow the motion --- with a kinematic body, it will collide rigidly and will not have any momentum imparted upon itself from collisions. 您将能够使其缓慢地漂移或严格跟随运动-通过运动的身体,它将刚性碰撞,并且不会因碰撞而产生任何动量。

You will also need to figure out how to deal with the fact that the actual length of the kinematic body can and will change as fingers move. 您还需要弄清楚如何处理这样的事实,即运动主体的实际长度会随着手指的移动而发生变化。

Hope that helps 希望能有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM