How to translate SKPhysicsContact contactPoint into my SKSpriteNode position

828 views Asked by At

I've spent too long on this. Someone has solved this already, please help.

Enemy fires on my ship. SKPhysicsContact takes over and I get contactPoint. I explode the fired missile at the contactPoint, in world coordinates. All good. Now I would like to use the point, not in the scene coordinates returned by contactPoint, but in my ship coordinates to start emitting smoke from the ship, where I've been hit. I've used convertPoint function before, with success, but I can't seem to get it right here...Docs say the contactPoint is expressed in Scene coordinates, while myShip has its coordinates, living as a child of a world node, which is a child of the scene node. They are in the same Node hierarchy. I think...I have a Scene->World->Camera, where myShip is a child of World. My code, I think, is saying convert contactPoint from Scene coordinates to coordinates in myShip. But this does not work. Nor does any other combination. What am I missing? I suspect the Camera hierarchy, but unsure. The numbers being returned into smoke.position are way out of whack...

- (SKEmitterNode *) newSmokeEmitter: (SKPhysicsContact *) contact
{
    NSString *smokePath = [[NSBundle mainBundle] pathForResource:@"ShipSmoke" ofType:@"sks"];
    SKEmitterNode *smoke = [NSKeyedUnarchiver unarchiveObjectWithFile:smokePath];

    smoke.targetNode = myShip;
    smoke.name = @"shipSmoke";
    smoke.position = [self convertPoint:contact.contactPoint toNode:myShip];

    //my temporary kludge that places the smoke on the ship, randomly

    //smoke.position = CGPointMake(skRand(-25,25), skRand(-25,+25));

    NSLog(@"Ship at world pos: %f,%f", myShip.position.x, myShip.position.y);
    NSLog(@"Contact at scene pos: %f,%f", contact.contactPoint.x, contact.contactPoint.y);
    NSLog(@"Smoke position at ship pos: %f,%f", smoke.position.x, smoke.position.y);
    [myShip addChild:smoke];
    return smoke;
}
2

There are 2 answers

5
Skyler Lauren On

If I understand your node hierarchy correctly this could fix the issue.

CGPoint contact = [self convertPoint:contact.contactPoint toNode:self.world];
smoke.position = [self.world convertPoint:contact toNode:myShip];

I don't think you can convert the point directly to ship. You have to convert it down the hierarchy until you get to the node you want.

Hopefully that helps.

Edit

To verify that the actual contact point is on the scene where I would expect you could try this.

SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(50, 50)];
sprite.position = contact.contactPoint;
[self addChild:sprite];

This should add a sprite exactly where the contact point is if the point returned is in the scene coordinate system. If it it does show up at the right spot than it truly does come down to converting points correctly.

1
SwampThingTom On

If you haven't solved it already, the answer is to convert from the node's scene:

smoke.position = [self convertPoint:contact.contactPoint fromNode:self.scene];

Or, in Swift:

smoke.position = convertPoint(contact.contactPoint, fromNode: scene)