SKPhysicsJoint is joining at what appears to be incorrect coordinates

457 views Asked by At

In my simple archery game, I have defined an arrow node and a target node with associated physics bodies.

When I attempt to join them together using an SKPhysicsJointFixed (I have also tried other types), the behaviour is inaccurate with the joint seemingly created at random points before actually hitting the target node.

I have played with friction and restitution values and also SKShapeNode (with a CGPath) and SKSpriteNode (with a rectangle around the sprite) to define the target but the problem occurs with both.

When just using collisions, the arrows bounce off the correct locations of the target, which seems OK. It is only when the join occurs that the results become random on-screen, usually 10-20 points away from the target node "surface".

static const uint32_t arrowCategory = 0x1 << 1;
static const uint32_t targetCategory = 0x1 << 2;

- (SKSpriteNode *)createArrowNode
{
    SKSpriteNode *arrow = [[SKSpriteNode alloc] initWithImageNamed:@"Arrow.png"];

    arrow.position = CGPointMake(165, 110);
    arrow.name = @"arrowNode";

    arrow.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:arrow.frame.size];
    arrow.physicsBody.angularVelocity = -0.25;
    arrow.physicsBody.usesPreciseCollisionDetection = YES;

    arrow.physicsBody.restitution = 0.0;
    arrow.physicsBody.friction = 0.0;

    arrow.physicsBody.categoryBitMask = arrowCategory;
    arrow.physicsBody.collisionBitMask = targetCategory;
    arrow.physicsBody.contactTestBitMask = /*arrowCategory | */targetCategory | bullseyeCategory;

    return arrow;
}


-void(createTargetNode)
{
    SKSpriteNode *sprite = [[SKSpriteNode alloc] initWithImageNamed:@"TargetOutline.png"];
    sprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.size];

    sprite.position = CGPointMake(610, 100);
    sprite.name = @"targetNode";

    sprite.physicsBody.usesPreciseCollisionDetection = NO;
//    sprite.physicsBody.affectedByGravity = NO;
//    sprite.physicsBody.mass = 20000;
    sprite.physicsBody.dynamic = NO;
    sprite.physicsBody.friction = 0.0;
    sprite.physicsBody.restitution = 0.0;

    sprite.physicsBody.categoryBitMask = targetCategory;
    sprite.physicsBody.contactTestBitMask = targetCategory | arrowCategory;

    [self addChild:sprite];
}


- (void)didBeginContact:(SKPhysicsContact *)contact
{

    SKPhysicsBody *firstBody, *secondBody;

    if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
    {
        firstBody = contact.bodyA;
        secondBody = contact.bodyB;
    }

    else
    {
        firstBody = contact.bodyB;
        secondBody = contact.bodyA;
    }

    if ((firstBody.categoryBitMask & arrowCategory) != 0 &&
        (secondBody.categoryBitMask & targetCategory) != 0)
    {
        CGPoint contactPoint = contact.contactPoint;

        NSLog(@"contactPoint is %@", NSStringFromCGPoint(contactPoint));

        float contact_x = contactPoint.x;
        float contact_y = contactPoint.y;

        SKPhysicsJoint *joint = [SKPhysicsJointFixed jointWithBodyA:firstBody bodyB:secondBody anchor:(CGPoint)contactPoint ];

        [self.physicsWorld addJoint:joint];

        CGPoint bullseye = CGPointMake(590, 102.5);
        NSLog(@"Center is %@", NSStringFromCGPoint(bullseye));

        CGFloat distance = SDistanceBetweenPoints(contactPoint, bullseye);
        NSLog(@"Distance to bullseye is %f", distance);
}
0

There are 0 answers