访问所有具有相同 categoryBitMask 的单个对象
Accessing individual objects that all have the same categoryBitMask
我有几个游戏世界对象,玩家需要在 physicsBody.categoryBitMask 联系它们时单独与之交互。我没有为每个单独的对象使用单独的 categoryBitMask(对象数量超过 categoryBitMask 的限制,即 32),而是使用 1 个 categoryBitMask 并为所有对象单独命名。这是它在代码中的样子:
-(void)createCollisionAreas
{
if (_tileMap)
{
TMXObjectGroup *group = [_tileMap groupNamed:@"ContactZone"]; //Layer's name.
//Province gateway.
NSDictionary *singularObject = [group objectNamed:@"msgDifferentProvince"];
if (singularObject)
{
CGFloat x = [singularObject[@"x"] floatValue];
CGFloat y = [singularObject[@"y"] floatValue];
CGFloat w = [singularObject[@"width"] floatValue];
CGFloat h = [singularObject[@"height"] floatValue];
SKSpriteNode *object = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(w, h)];
object.name = @"provinceGateway";
object.position = CGPointMake(x + w/2, y + h/2);
object.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(w, h)];
object.physicsBody.categoryBitMask = terrainCategory;
object.physicsBody.contactTestBitMask = playerCategory;
object.physicsBody.collisionBitMask = 0;
object.physicsBody.dynamic = NO;
object.physicsBody.friction = 0;
object.hidden = YES;
[_backgroundLayer addChild:object];
}
/*More code written below. Too lazy to copy & paste it all*/
}
-(void)didBeginContact:(SKPhysicsContact *)contact
{
SKPhysicsBody *firstBody, *secondBody; //Create 2 placeholder reference's for the contacting objects.
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) //If bodyA has smallest of 2 bits...
{
firstBody = contact.bodyA; //...it is then the firstBody reference [Smallest of two (category) bits.].
secondBody = contact.bodyB; //...and bodyB is then secondBody reference [Largest of two bits.].
}
else //This is the reverse of the above code (just in case so we always know what's what).
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
/**BOUNDARY contacts*/
if ((firstBody.categoryBitMask == noGoCategory) && (secondBody.categoryBitMask == playerCategory))
{
//Boundary contacted by player.
if ([_backgroundLayer childNodeWithName:@"bounds"])
{
NSLog(@"Player contacted map bounds.");
}
if ([_backgroundLayer childNodeWithName:@"nogo"])
{
NSLog(@"Player can't go further.");
}
if ([_backgroundLayer childNodeWithName:@"provinceGateway"])
{
NSLog(@"Another province is ahead. Can't go any further.");
}
if ([_backgroundLayer childNodeWithName:@"slope"])
{
NSLog(@"Player contacted a slope.");
}
}
问题是,在 didBeginContact 方法中,当玩家接触任何对象时,所有代码都会被执行。甚至是玩家尚未接触过的对象的代码。这意味着 IF 语句,例如 if ([_backgroundLayer childNodeWithName:@"slope"]) 是不完整的。有人能告诉我如何正确写出单个对象接触的 IF 语句吗? didBeginContact 中的以下 IF 语句也不起作用:
if ([_player intersectsNode:[_backgroundLayer childNodeWithName:@"slope"]])
您的 if
语句都只是检查子项是否存在,它们似乎都这样做了。我想你想检查的是碰撞节点是否有你要找的名字,所以改变:
if ([_backgroundLayer childNodeWithName:@"bounds"])
至:
if ([firstBody.node.name isEqualToString:@"bounds"])
我有几个游戏世界对象,玩家需要在 physicsBody.categoryBitMask 联系它们时单独与之交互。我没有为每个单独的对象使用单独的 categoryBitMask(对象数量超过 categoryBitMask 的限制,即 32),而是使用 1 个 categoryBitMask 并为所有对象单独命名。这是它在代码中的样子:
-(void)createCollisionAreas
{
if (_tileMap)
{
TMXObjectGroup *group = [_tileMap groupNamed:@"ContactZone"]; //Layer's name.
//Province gateway.
NSDictionary *singularObject = [group objectNamed:@"msgDifferentProvince"];
if (singularObject)
{
CGFloat x = [singularObject[@"x"] floatValue];
CGFloat y = [singularObject[@"y"] floatValue];
CGFloat w = [singularObject[@"width"] floatValue];
CGFloat h = [singularObject[@"height"] floatValue];
SKSpriteNode *object = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(w, h)];
object.name = @"provinceGateway";
object.position = CGPointMake(x + w/2, y + h/2);
object.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(w, h)];
object.physicsBody.categoryBitMask = terrainCategory;
object.physicsBody.contactTestBitMask = playerCategory;
object.physicsBody.collisionBitMask = 0;
object.physicsBody.dynamic = NO;
object.physicsBody.friction = 0;
object.hidden = YES;
[_backgroundLayer addChild:object];
}
/*More code written below. Too lazy to copy & paste it all*/
}
-(void)didBeginContact:(SKPhysicsContact *)contact
{
SKPhysicsBody *firstBody, *secondBody; //Create 2 placeholder reference's for the contacting objects.
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) //If bodyA has smallest of 2 bits...
{
firstBody = contact.bodyA; //...it is then the firstBody reference [Smallest of two (category) bits.].
secondBody = contact.bodyB; //...and bodyB is then secondBody reference [Largest of two bits.].
}
else //This is the reverse of the above code (just in case so we always know what's what).
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
/**BOUNDARY contacts*/
if ((firstBody.categoryBitMask == noGoCategory) && (secondBody.categoryBitMask == playerCategory))
{
//Boundary contacted by player.
if ([_backgroundLayer childNodeWithName:@"bounds"])
{
NSLog(@"Player contacted map bounds.");
}
if ([_backgroundLayer childNodeWithName:@"nogo"])
{
NSLog(@"Player can't go further.");
}
if ([_backgroundLayer childNodeWithName:@"provinceGateway"])
{
NSLog(@"Another province is ahead. Can't go any further.");
}
if ([_backgroundLayer childNodeWithName:@"slope"])
{
NSLog(@"Player contacted a slope.");
}
}
问题是,在 didBeginContact 方法中,当玩家接触任何对象时,所有代码都会被执行。甚至是玩家尚未接触过的对象的代码。这意味着 IF 语句,例如 if ([_backgroundLayer childNodeWithName:@"slope"]) 是不完整的。有人能告诉我如何正确写出单个对象接触的 IF 语句吗? didBeginContact 中的以下 IF 语句也不起作用:
if ([_player intersectsNode:[_backgroundLayer childNodeWithName:@"slope"]])
您的 if
语句都只是检查子项是否存在,它们似乎都这样做了。我想你想检查的是碰撞节点是否有你要找的名字,所以改变:
if ([_backgroundLayer childNodeWithName:@"bounds"])
至:
if ([firstBody.node.name isEqualToString:@"bounds"])