问题
I'm trying to detect collisions between two sprites but I'm unable to do this with a child sprite.
self.player = [[Player alloc] initWithImageNamed:@"player"];
self.player.position = CGPointMake(150, 75);
[self addChild:self.player];
_object = [SKSpriteNode spriteNodeWithImageNamed:@"object"];
_object.position = CGPointMake(-40, 27);
[self.player addChild:_object];
then I have collision detetion like this
- (void)checkCollisions {
[self.map enumerateChildNodesWithName:@"enemy"
usingBlock:^(SKNode *node, BOOL *stop){SKSpriteNode *enemy = (SKSpriteNode *)node;
if (CGRectIntersectsRect(enemy.frame, _object.frame)) {
[enemy removeFromParent];
}
}]; }
*This does not work!!! but if I use :
CGRectIntersectsRect(enemy.frame, self.player.frame)
I can detect a collision with the main body. how do I do collision detection for a child of another sprite?
回答1:
The child node's position
and frame
property are relative to it's parent
, which you need to account for in your code.
SKNode
has two methods that can help you with converting the position
of a given SKNode
to/from the coordinate spaces of another node:
convertPoint:fromNode:
convertPoint:toNode:
You can use those to convert a SKNode
's position
property to another coordinate space. What you want to do is convert the _object
's position to the coordinate space of the enemy or visa versa and then use a temporary CGRect
with that new position for your CGRectIntersectsRect
check.
Here's an example :
CGPoint globalPosition = [self.player convertPoint:_object.position toNode:self.player.parent];
CGRect tempRect = CGRectMake(globalPosition.x, globalPosition.y, _object.frame.size.width, _object.frame.size.height);
if (CGRectIntersectsRect(enemy.frame, _object.frame))
{
// collision occurred
}
This code is assuming that your enemy and your player are in the same coordinate space. (have the same parent)
回答2:
This happens because _object
is a child node for self.player
, and enemy
node is a child node for self.map
node. Both nodes should have same parent if you want to compare their frames.
I suggest you to use Sprite Kit's built-in collision handling mechanism:
// Object:
_object = [SKSpriteNode spriteNodeWithImageNamed:@"object"];
_object.position = CGPointMake(-40, 27);
_object.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_object.frame.size;
_object.physicsBody.categoryBitMask = OBJECT_CATEGORY;
_object.physicsBody.contactTestBitMask = ENEMY_CATEGORY;
_object.physicsBody.collisionBitMask = 0;
[self.player addChild:_object];
// Enemy:
// init enemy: SKSpriteNode *enemy = [SKSpriteNode spriteNodeWithImageNamed:@"enemy"];
enemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:enemy.frame.size;
enemy.physicsBody.categoryBitMask = ENEMY_CATEGORY;
enemy.physicsBody.contactTestBitMask = OBJECT_CATEGORY;
enemy.physicsBody.collisionBitMask = 0;
// add enemy to the scene: [self addChild:enemy];
// Define that your SKScene conforms to SKPhysicsContactDelegate protocol:
.....
@interface MyScene : SKScene <SKPhysicsContactDelegate>
....
// SKScene.m:
static uint32_t const OBJECT_CATEGORY = 0x1 << 0;
static uint32_t const ENEMY_CATEGORY = 0x1 << 1;
@implementation MyScene
- (id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
.......
self.physicsWorld.contactDelegate = self;
........
}
return self;
}
.......
- (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 & OBJECT_CATEGORY) != 0) &&
(secondBody.categoryBitMask & ENEMY_CATEGORY) != 0) {
NSLog(@"Collision detected!");
}
@end
来源:https://stackoverflow.com/questions/21870605/sprite-kit-collision-detection-with-child-sprite