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. 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.
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.
I've read this: Cocos2d - Collision Detection of Rotated Sprite
...and already gone through this: Ray Wenderlich Collision Detection
My latest ccTouchesMoved
method looks like this:
- (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. How can I accomplish this with Box2D?
Does anyone have any suggestions?