Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sprite Kit pin joints appear to have an incorrect anchor

I'm testing out pin joints with Sprite Kit, and I'm finding something unusual happening.

My desired setup is this: one wide, flat box, and two circles; the circles are connected via SKPhysicsPinJoints to the box, so they can act as wheels.

Here's my code. I've tried to make it as concise as possible:

- (SKNode*) createWheelWithRadius:(float)wheelRadius {
    CGRect wheelRect = CGRectMake(-wheelRadius, -wheelRadius, wheelRadius*2, wheelRadius*2);

    SKShapeNode* wheelNode = [[SKShapeNode alloc] init];
    wheelNode.path = [UIBezierPath bezierPathWithOvalInRect:wheelRect].CGPath;

    wheelNode.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:wheelRadius];

    return wheelNode;
}


- (void) createCar {

    // Create the car
    SKSpriteNode* carNode = [SKSpriteNode spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(150, 50)];
    carNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carNode.size];
    carNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
    [self addChild:carNode];

    // Create the left wheel
    SKNode* leftWheelNode = [self createWheelWithRadius:30];
    leftWheelNode.position = CGPointMake(carNode.position.x-80, carNode.position.y);
    [self addChild:leftWheelNode];

    // Create the right wheel
    SKNode* rightWheelNode = [self createWheelWithRadius:30];
    rightWheelNode.position = CGPointMake(carNode.position.x+80, carNode.position.y);
    [self addChild:rightWheelNode];

    // Attach the wheels to the body
    CGPoint leftWheelPosition = leftWheelNode.position;
    CGPoint rightWheelPosition = rightWheelNode.position;

    SKPhysicsJointPin* leftPinJoint = [SKPhysicsJointPin jointWithBodyA:carNode.physicsBody bodyB:leftWheelNode.physicsBody anchor:leftWheelPosition];
    SKPhysicsJointPin* rightPinJoint = [SKPhysicsJointPin jointWithBodyA:carNode.physicsBody bodyB:rightWheelNode.physicsBody anchor:rightWheelPosition];

    [self.physicsWorld addJoint:leftPinJoint];
    [self.physicsWorld addJoint:rightPinJoint];
}

What I'm expecting is that the pin joints are anchored at their centre points; however, when I test this, the anchors for the joints appear to be far off.

Am I missing something really obvious?

like image 928
Jon Manning Avatar asked Oct 13 '13 06:10

Jon Manning


2 Answers

I also had this issue and the cause is setting the physics body before setting the sprites position.

carNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carNode.size];
carNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

Change the above to

carNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
carNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carNode.size];

It should work. Thanks Smick.

SpriteKit: How to create Basic Physics Joints

like image 135
Bavan Avatar answered Nov 15 '22 13:11

Bavan


Try this code, I used yours and got weird issues, so started from scratch.

- (SKShapeNode*) makeWheel
{
    SKShapeNode *wheel = [[SKShapeNode alloc] init];
    CGMutablePathRef myPath = CGPathCreateMutable();
    CGPathAddArc(myPath, NULL, 0,0, 16, 0, M_PI*2, YES);
    wheel.path = myPath;
    return wheel;
}


- (void) createCar 
{

    self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0, 0, self.size.width, self.size.height)];

    // 1. car body
    SKSpriteNode *carBody = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(120, 8)];
    carBody.position = CGPointMake(200, 200);
    carBody.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carBody.size];
    [self addChild:carBody];

    // 2. wheels
    SKShapeNode *leftWheel = [self makeWheel];
    leftWheel.position = CGPointMake(carBody.position.x - carBody.size.width / 2, carBody.position.y);
    leftWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:16];
    [self addChild:leftWheel];

    SKShapeNode *rightWheel = [self makeWheel];
    rightWheel.position = CGPointMake(carBody.position.x + carBody.size.width / 2, carBody.position.y);
    rightWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:16];
    [self addChild:rightWheel];

    // 3. Join wheels to car
    [self.physicsWorld addJoint:[SKPhysicsJointPin jointWithBodyA:carBody.physicsBody bodyB:leftWheel.physicsBody anchor:leftWheel.position]];
    [self.physicsWorld addJoint:[SKPhysicsJointPin jointWithBodyA:carBody.physicsBody bodyB:rightWheel.physicsBody anchor:rightWheel.position]];

    // 4. drive car
    [carBody.physicsBody applyForce:CGVectorMake(10, 0)];
}
like image 36
DogCoffee Avatar answered Nov 15 '22 12:11

DogCoffee