SKSpriteNode теряет свои свойства physicsBody

Я использую SpriteKit для создания игры, в которой перемещаются объекты внизу карты. Объекты - крокодилы и монеты.

Сцена использует NSTimer для вызова этого селектора:

timer  = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(generateBottomSprite) userInfo:nil repeats:YES];


-(void) generateBottomSprite{

int random = (arc4random() % difficulty+3) + difficulty-3;
if (counter >random){
    SKSpriteNode *bottomSprite;
    if (random>difficulty){
        bottomSprite  = [SKSpriteNode spriteNodeWithImageNamed:@"crocodile"];
        bottomSprite.size = CGSizeMake(70, 120);
        bottomSprite.physicsBody.categoryBitMask = crocMask;

    }else{
        bottomSprite = [SKSpriteNode spriteNodeWithImageNamed:@"coin"];
        bottomSprite.size = CGSizeMake(50, 50);
        bottomSprite.physicsBody.categoryBitMask = coinMask;

    }

    //create a crocodile
    bottomSprite.position = CGPointMake(self.frame.size.width,bottomSprite.frame.size.height/2);
    bottomSprite.name = @"bottomSprite";



    [self addChild: bottomSprite];

    counter = 0;

        [self enumerateChildNodesWithName:@"bottomSprite" usingBlock: ^(SKNode *node, BOOL *stop) {
            node.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:node.frame.size];
            node.physicsBody.affectedByGravity = NO;
            node.physicsBody.mass = 8000.0;
            node.physicsBody.friction = 2.50;
            node.physicsBody.usesPreciseCollisionDetection = YES;

        }];

}

}

Проблема: все свойства physicsWorld повторно инициализируются при каждом вызове селектора, и я должен перебирать дочерние элементы сцены, чтобы переназначить их.

Почему свойства повторно инициализируются?


person user3157423    schedule 22.03.2014    source источник
comment
Правильно ли я предполагаю, что перечисление дочерних узлов внизу — это то, чего вы хотели бы избежать?   -  person radnoise    schedule 23.03.2014
comment
да, именно проблема.   -  person user3157423    schedule 23.03.2014
comment
Не уверен, что это связано, но повторюсь: не используйте NSTimer в приложениях Sprite Kit. Используйте методы SKScene update:/didSimulatePhysics для выполнения повторяющихся задач или используйте SKAction runBlock в паре с waitForDuration. Проблема: NSTimer может сработать в любой момент цикла обновления Sprite Kit. NSTimer будет срабатывать даже при паузе или переходе узла/сцены.   -  person LearnCocos2D    schedule 23.03.2014
comment
Спасибо за совет, но это тоже не решает проблему   -  person user3157423    schedule 23.03.2014


Ответы (1)


вы устанавливаете битовую маску категории перед созданием самого skphysicsbody

bottomSprite  = [SKSpriteNode spriteNodeWithImageNamed:@"crocodile"];
bottomSprite.size = CGSizeMake(70, 120);
//add the following
bottomSprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bottomSprite.frame.size];
///////////////
bottomSprite.physicsBody.categoryBitMask = crocMask;

переместить все настройки физики за пределы перечисления вот так

if (counter >random){
    SKSpriteNode *bottomSprite;
int currentBitMask;
if (random>difficulty){
    bottomSprite  = [SKSpriteNode spriteNodeWithImageNamed:@"crocodile"];
    bottomSprite.size = CGSizeMake(70, 120);
    currentBitMask = crocMask;
}else{
    bottomSprite = [SKSpriteNode spriteNodeWithImageNamed:@"coin"];
    bottomSprite.size = CGSizeMake(50, 50);
    currentBitMask  = coinMask;

}

**bottomSprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bottomSprite.frame.size];**
bottomSprite.physicsBody.categoryBitMask = currentBitMask ;
bottomSprite.physicsBody.affectedByGravity = NO;
bottomSprite.physicsBody.mass = 8000.0;//way too high
bottomSprite.physicsBody.friction = 2.50;//probably high
bottomSprite.physicsBody.usesPreciseCollisionDetection = YES;//overkill, set only if critical


//create a crocodile
bottomSprite.position = CGPointMake(self.frame.size.width,bottomSprite.frame.size.height/2);
bottomSprite.name = @"bottomSprite";

[self addChild: bottomSprite];

вы также можете использовать метод обновления в skscene и nstimeintervals для измерения времени, пока вы не пройдете полсекунды, а затем вызовете метод generateBottomSprite, он должен быть более эффективным, чем использование дополнительного NSTimer.

Не стесняйтесь спрашивать, если что-то неясно, надеюсь, это поможет.

person rockstarr    schedule 23.03.2014