2015-01-17 2 views
0

Хорошо, поэтому в моей игре у меня есть блок кода, который порождает спрайт («враг») каждые х раз. Он порождает спрайт вверх, и спрайт падает.Почему физика не работает так, как я ее хочу?

Должно произойти следующее: Спрайт падает, он касается земли или другого врага, затем он изменяется на статичный, поэтому его нельзя перемещать.

Что происходит: Иногда это работает, но иногда (особенно когда х количество времени меньше и спрайты икру чаще) спрайт вдруг изменяется на статический, пока он еще в воздухе.

Почему это происходит?

Вот код:

в GameScene.m, в createSceneContents, метод, который вызывается didMoveToView:

self.physicsWorld.contactDelegate = self; 

SKSpriteNode *bottom = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(self.frame.size.width, 10)]; 
bottom.position = CGPointMake(self.frame.size.width/2, 0); 
bottom.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bottom.size]; 
bottom.physicsBody.dynamic = NO; 
bottom.physicsBody.restitution = 0; 
bottom.physicsBody.categoryBitMask = self.bottomCategory; 
bottom.physicsBody.contactTestBitMask = self.enemyCategory; 

[self spawnObject]; 
[self addChild:self.world]; 
[self.world addChild:bottom]; 

в spawnObject, метод, который вызывается с помощью createSceneContents :

if (self.isPaused == NO){ 

    self.spawningSpeed = 1; 
    self.enemyData = [[Enemy alloc]init]; 
    SKAction *wait = [SKAction waitForDuration:self.spawningSpeed]; 
    SKAction *run = [SKAction runBlock:^{ 

     SKSpriteNode *aNewEnemy = [self.enemyData createEnemyWithSize:self.customUnit andWidth:self.frame.size.width andHeight:self.frame.size.height + self.player.position.y andPlayerPosition:self.player.position.x]; 
     aNewEnemy.physicsBody.allowsRotation = NO; 
     aNewEnemy.physicsBody.categoryBitMask = self.enemyCategory; 
     aNewEnemy.physicsBody.collisionBitMask = self.enemyCategory | self.bottomCategory; 
     aNewEnemy.physicsBody.contactTestBitMask = self.enemyCategory | self.bottomCategory; 
     [self.world addChild:aNewEnemy]; 



    }]; 
    SKAction *action = [SKAction repeatActionForever:[SKAction sequence:@[wait,run]]]; 
    [self runAction:action withKey:@"action"]; 

в createEnemyWithSize: andWidth: andHeight: andPlayerPosition :, в Enemy.m:

self.enemy = [SKSpriteNode spriteNodeWithImageNamed:@"block.png"]; 
self.enemy.size = CGSizeMake(size - 5, size - 5); 
self.enemy.name = @"fallingEnemy"; 
self.enemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(size - 1, size - 1)]; 
self.enemy.physicsBody.restitution = 0; 
self.enemy.physicsBody.allowsRotation = NO; 

int column1 = width/7; 
int column2 = column1 * 2; 
int column3 = column1 * 3; 
int column4 = column1 * 4; 
int column5 = column1 * 5; 
int column6 = column1 * 6; 
int halfAColumn = column1/2; 

if (position > 0 && position < column1) { 
    self.enemy.position = CGPointMake(halfAColumn, height - size); 

}else if (position > column1 && position < column2) { 
    self.enemy.position = CGPointMake((column2-halfAColumn), height - size); 

}else if (position > column2 && position < column3) { 
    self.enemy.position = CGPointMake((column3-halfAColumn), height - size); 

}else if (position > column3 && position < column4) { 
    self.enemy.position = CGPointMake((column4-halfAColumn), height - size); 

}else if (position > column4 && position < column5) { 
    self.enemy.position = CGPointMake((column5-halfAColumn), height - size); 

}else if (position > column5 && position < column6) { 
    self.enemy.position = CGPointMake((column6-halfAColumn), height - size); 

}else if (position > column6 && position < width) { 
    self.enemy.position = CGPointMake((width-halfAColumn), height - size); 

} 

return self.enemy; 

в didBeginContact, в GameScene.m:

SKPhysicsBody *enemyBodyA, *bottomBodyA, *enemyBodyB, *bottomBodyB; 
if (contact.bodyA.categoryBitMask == self.enemyCategory) { 
     enemyBodyA = contact.bodyA; 

}else if (contact.bodyA.categoryBitMask == self.bottomCategory) { 

     bottomBodyA = contact.bodyA; 

} 
    if (contact.bodyB.categoryBitMask == self.enemyCategory) { 
     enemyBodyB = contact.bodyB; 

}else if (contact.bodyB.categoryBitMask == self.bottomCategory) { 

     bottomBodyB = contact.bodyB; 

} 

     if (enemyBodyA == contact.bodyA && enemyBodyB == contact.bodyB) { 

     [self.enemyData changeBlock]; 


     NSLog(@"Change1"); 
    } 
    if (contact.bodyA == enemyBodyA && contact.bodyB == bottomBodyB) { 
     NSLog(@"Change2"); 
     [self.enemyData changeBlock]; 


    } 
    if (contact.bodyB == enemyBodyB && contact.bodyA == bottomBodyA) { 
     NSLog(@"Change3"); 
     [self.enemyData changeBlock]; 


    } 

в changeBlock, в Enemy.m :

-(void)changeBlock { 
self.enemy.physicsBody.dynamic = NO; 
self.enemy.name = @"staticEnemy"; 
} 

значения Bitmask в createSce neContents:

self.playerCategory = 1; 
self.enemyCategory = 2; 
self.edgeCategory = 4; 
self.bottomCategory = 8; 
+0

Что такое self.enemyData, на которую вы вызываете метод changeBlock в делегате контакта? – ZeMoon

+0

Объект класса Enemy – Squid

+0

Вам необходимо прекратить ссылаться на созданный вражеский узел как свойство объекта enemyData. Используйте свойство body.node в делете делегата, чтобы связать узел. Нынешний путь это испортить. Я пишу ответ, и опубликую его через несколько минут. – ZeMoon

ответ

0

Вы можете потерять ссылку на врага, который не получил контакта перед другим порождена. Следовательно, требуется несколько изменений. Вам не нужно свойство self.enemy в классе врагов вообще.

Прежде всего, измените метод changeBlock, чтобы он мог выполняться на любом блоке, который передается в качестве параметра.

-(void)changeBlock:(SKSpriteNode*)block { 
    block.physicsBody.dynamic = NO; 
    block.name = @"staticEnemy"; 
} 

И затем очистить метод делегирования контактов.

-(void)didBeginContact:(SKPhysicsContact *)contact 
{ 
    SKPhysicsBody *firstBody, *secondBody; 

    //This is a useful technique for organising bodies in the contact delegate 
    if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) { 
     firstBody = contact.bodyA; 
     secondBody = contact.bodyB; 
    } else { 
     firstBody = contact.bodyB; 
     secondBody = contact.bodyA; 
    } 
    //Since enemyCategory < bottomCategory, the firstBody is an enemy node, and second either an enemy or bottom node 

    if (firstBody.categoryBitMask == self.enemyCategory && secondBody.categoryBitMask == self.bottomCategory) { 
     [self.enemyData changeBlock: (SKSpriteNode*)firstBody.node]; 
    } else if (firstBody.categoryBitMask == self.enemyCategory && secondBody.categoryBitMask == self.enemyCategory) { 
     [self.enemyData changeBlock: (SKSpriteNode*)firstBody.node]; 
     [self.enemyData changeBlock: (SKSpriteNode*)secondBody.node]; 
    } 
} 

Я не уверен, что ваша игра о том, что так изменилось, как вы пожелаете. Но я надеюсь, что вы поняли эту идею.

+0

Это дает мне предупреждение, когда я передаю спраттоды для замены блока, потому что тела - это только узлы? Должен ли я изменить его или игнорировать? Способ организации тел действительно умный. Большое спасибо – Squid

+0

Да, это не должно иметь никакого значения в любом случае. Сделайте то, что требуется для удаления предупреждений. – ZeMoon

+0

Я также думаю, что вы совершили небольшую ошибку. Вы проверяете личность first/secondBody равны категории вместо first/secondBody.categoryBitMask – Squid

Смежные вопросы