I clearly don't understand the SKPhysicsJoint very well, but there is so little info on the web yet, other than the Apple docs of course. What is wrong with the following code, which I would think should keep the head and neck permanently joined - my intention is that they act like 2 pieces of paper with a pin, so that they can rotate a bit, but not just totally come apart. When I run this code, they fall to the bottom of the SKScene they're in, hit the ground, then the head falls off the body.
Maybe the joint is not moving WITH them or something, it's just staying in place while they move??
self.head = [SKSpriteNode spriteNodeWithImageNamed:@"head.png"];
self.head.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.head.size];
self.head.physicsBody.mass = 0.05;
self.head.physicsBody.dynamic = YES;
self.chest = [SKSpriteNode spriteNodeWithImageNamed:@"chest_neck"];
self.chest.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.chest.size];
self.chest.physicsBody.mass = 0.05;
self.chest.physicsBody.dynamic = YES;
self.leftLeg = [SKSpriteNode spriteNodeWithImageNamed:@"left_leg"];
self.leftLeg.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.leftLeg.size];
self.leftLeg.physicsBody.mass = 10;
self.leftLeg.physicsBody.dynamic = YES;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
self.head.position = CGPointMake(282, 220);
self.chest.position = CGPointMake(282, 130);
self.leftLeg.position = CGPointMake(282, 10);
} else {
self.head.position = CGPointMake(512, 380);
self.chest.position = CGPointMake(512, 290);
self.leftLeg.position = CGPointMake(512, 10);
}
[self addChild:self.head];
[self addChild:self.chest];
[self addChild:self.leftLeg];
self.chestJointPinAnchor = CGPointMake(self.chest.position.x, self.chest.position.y+39);
self.chestJointPin = [SKPhysicsJointPin jointWithBodyA:self.head.physicsBody bodyB:self.chest.physicsBody anchor:self.chestJointPinAnchor];
[self.physicsWorld addJoint:self.chestJointPin];
This is because you set sprite's position after you set up its physicsBody property.
I haven't discovered any mention of that in documentation, but I broke my head last weekend trying to figure out why my manually created rope works, but recursively one doesn't.
SpriteNodes' position MUST be set before physicsBody.
So, just reorder your code somehow like that:
self.head = [SKSpriteNode spriteNodeWithImageNamed:@"head.png"];
self.chest = [SKSpriteNode spriteNodeWithImageNamed:@"chest_neck"];
self.leftLeg = [SKSpriteNode spriteNodeWithImageNamed:@"left_leg"];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
self.head.position = CGPointMake(282, 220);
self.chest.position = CGPointMake(282, 130);
self.leftLeg.position = CGPointMake(282, 10);
} else {
self.head.position = CGPointMake(512, 380);
self.chest.position = CGPointMake(512, 290);
self.leftLeg.position = CGPointMake(512, 10);
self.head.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.head.size];
self.head.physicsBody.mass = 0.05;
self.head.physicsBody.dynamic = YES;
self.chest.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.chest.size];
self.chest.physicsBody.mass = 0.05;
self.chest.physicsBody.dynamic = YES;
self.leftLeg.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.leftLeg.size];
self.leftLeg.physicsBody.mass = 10;
self.leftLeg.physicsBody.dynamic = YES;
}
Oh, I've noticed, you've already found an answer by yourself... Could you please mark your question as answered then.
That seems about right.
A pin joint allows both bodies to rotate around the joint's anchor point. A real world example is an analog clock. Or a bicycle's pedals. Or a car wheel's axle.
One thing you have to know is that bodies connected through a joint will not collide with each other. You can use the pin joint limits though to prevent the head from doing a full 360 spin around the pin joint anchor.
Okay, so I found out that this is an actual bug in Sprite Kit. The fix is to set the sprite's position before setting its physicsBody. I did that and it worked perfectly, as expected.
Additionally, not invalidating what was said above, but apparently the physics engine assumes the scene's anchorPoint is left at (0, 0). If you change it to something else, the physics engine will still treat it like (0, 0).