SKScene在通过NSTimer添加SpriteNode时不会检测到接触



概述:我在场景顶部添加了一个敌人。敌人最初以150 x的速度向右移动。这张地图有左墙和右墙。当敌人攻击左右墙时,他应该立即逆转方向。

问题:当我从initWithSize调用函数spawnEnemy时,当敌人击中每堵墙时,敌人的行为就像预期的那样反转方向。当我使用NSTimer每2秒调用一次spawnEnemy时,SKScene无法识别敌人与墙壁的接触,也无法逆转敌人的方向。代码如下所示。

刷出敌人方法:

-(void)spawnEnemy{
    self.testingEnemy = [SKSpriteNode spriteNodeWithImageNamed:@"normalEnemy.png"];
    self.testingEnemy.position = (CGPoint) {
        CGRectGetMidX(self.scene.frame),
        300
    };
    self.testingEnemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.testingEnemy.frame.size];
    self.testingEnemy.physicsBody.dynamic = TRUE;
    self.testingEnemy.physicsBody.affectedByGravity = TRUE;
    self.testingEnemy.physicsBody.mass = 0.00150;
    self.testingEnemy.physicsBody.restitution = 0.0;
    self.testingEnemy.physicsBody.allowsRotation = FALSE;
    self.testingEnemy.physicsBody.linearDamping = 0.0;
    [self addChild:self.testingEnemy];
}

initWithSize

-(id)initWithSize:(CGSize)size {
    if (self = [super initWithSize:size]) {
        //[self spawnEnemy]; <--- This works with expected behavior
        [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(spawnEnemy) userInfo:nil repeats:NO];
    }
    return self
}

didBeginContact

- (void)didBeginContact:(SKPhysicsContact *)contact
{   
    if (contact.bodyA == self.testingEnemy.physicsBody && contact.bodyB == [self.map rightWall].physicsBody) {
        NSLog(@"Hit right wall");
        normalEnemyVelocityX = -normalEnemyVelocityX;
    }
}

这里是项目文件的链接:

https://www.dropbox.com/s/e59piru3q1hcu0e/Goldrush.zip?dl=0

My two cents…

  1. 你没有处理接触的情况。bodyA是墙和接触。bodyB是敌人。
  2. 你在哪里设置categoryBitMask和contactTestBitMask?
  3. 你应该考虑使用SKAction而不是ntimer,因为当你暂停/恢复游戏时,SKActions会适当地暂停/恢复。

这里有一个例子…

SKAction *wait = [SKAction waitForDuration:2.0];
SKAction *spawn = [SKAction performSelector:@selector(spawnEnemy) onTarget:self];
SKAction *waitThenSpawn = [SKAction sequence:@[wait, spawn]];
[self runAction:[SKAction repeatActionForever:waitThenSpawn]];

编辑:试试下面的…

1)代码没有检查接触体是否交换,如果场景中有多个敌人,它将不起作用。下面是解决这些问题的方法:

static inline SKSpriteNode *bodyToNode(SKPhysicsBody *body1,
                                       SKPhysicsBody *body2,
                                       NSString *name) {
    SKSpriteNode *node = nil;
    if ([body1.node.name isEqualToString:name]) {
        node = (SKSpriteNode *)body1.node;
    }
    else if ([body2.node.name isEqualToString:name]) {
        node = (SKSpriteNode *)body2.node;
    }
    return node;
}
- (void)didBeginContact:(SKPhysicsContact *)contact
{
    SKSpriteNode *enemyNode = nil;
    SKSpriteNode *wallNode = nil;
    enemyNode = bodyToNode (contact.bodyA, contact.bodyB, @"enemy");
    wallNode = bodyToNode (contact.bodyA,contact.bodyB, @"wall");
    if (enemyNode && wallNode) {
        NSLog(@"Hit right wall %@", self.testingEnemy);
        normalEnemyVelocityX = -normalEnemyVelocityX;
    }
} 

2)从地图中移动以下内容。

static const uint32_t playerCategory =  1 << 0;
static const uint32_t platformCategory =  1 << 1;

3)你没有为敌人设置类别,你需要为敌人命名,这样didBeginContact才能正常工作。将以下内容添加到test方法中:

self.testingEnemy.physicsBody.categoryBitMask = playerCategory;
self.testingEnemy.name = @"enemy";

4)在地图。M,在代码的适当位置添加以下内容:

self.leftWall.name = @"wall";
self.rightWall.name = @"wall";
5)从语句中删除playerCategory:
self.bottomRightHorizWall.physicsBody.contactTestBitMask = platformCategory;

最新更新