子精灵的精灵套件碰撞检测
Posted
技术标签:
【中文标题】子精灵的精灵套件碰撞检测【英文标题】:sprite kit collision detection with child sprite 【发布时间】:2014-02-19 03:48:12 【问题描述】:我正在尝试检测两个精灵之间的碰撞,但我无法对子精灵执行此操作。
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];
然后我有这样的碰撞检测
- (void)checkCollisions
[self.map enumerateChildNodesWithName:@"enemy"
usingBlock:^(SKNode *node, BOOL *stop)SKSpriteNode *enemy = (SKSpriteNode *)node;
if (CGRectIntersectsRect(enemy.frame, _object.frame))
[enemy removeFromParent];
];
*这不起作用!!!但如果我使用:
CGRectIntersectsRect(enemy.frame, self.player.frame)
我可以检测到与主体的碰撞。如何为另一个精灵的孩子进行碰撞检测?
【问题讨论】:
【参考方案1】:子节点的position
和frame
属性相对于它的parent
,您需要在代码中加以说明。
SKNode
有两种方法可以帮助您将给定SKNode
的position
与另一个节点的坐标空间相互转换:
convertPoint:fromNode:
convertPoint:toNode:
您可以使用它们将SKNode
的position
属性转换为另一个坐标空间。您要做的是将_object
的位置转换为敌人的坐标空间,反之亦然,然后使用带有新位置的临时CGRect
进行CGRectIntersectsRect
检查。
这是一个例子:
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
这段代码假设你的敌人和你的玩家在同一个坐标空间中。 (有相同的父)
【讨论】:
我的回答是澄清为什么您的代码没有按预期工作。学习 SpriteKit 的内置碰撞如何工作是值得的。值得花时间通过 Sprite Kit 参考或教程了解它,这样您就可以清楚地了解它的工作原理。 感谢我目前使用物理引擎的项目太过分了。这就是我改用 CGRectIntersectsRect 的原因。【参考方案2】:这是因为_object
是self.player
的子节点,而enemy
节点是self.map
节点的子节点。如果要比较它们的帧,两个节点应该具有相同的父节点。
我建议你使用 Sprite Kit 内置的碰撞处理机制:
// 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
【讨论】:
以上是关于子精灵的精灵套件碰撞检测的主要内容,如果未能解决你的问题,请参考以下文章