2016-06-28 1 views
0

Я делаю игру в комплекте спрайтов (2D).игра с быстрым спрайт-комплектом, когда я стреляю по врагу, иногда пуля проходит через врага, как я могу это исправить?

У меня есть этот код:

meteor.physicsBody = SKPhysicsBody(rectangleOfSize: enemy.size) 

и у меня есть метеоритное изображение, которое нужно уничтожить, но иногда, когда я стреляю на моем устройстве метеора пуля проходит через метеорный это ошибка или я сделал что-то не так? и Как я могу исправить эту проблему?

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

func fireBullet() { 

    let bullet = SKSpriteNode(imageNamed: "bullet") 
    bullet.name = "Bullet" 
    bullet.setScale(2.9) 
    bullet.position = player.position 
    bullet.zPosition = 1 
    bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.size) 
    bullet.physicsBody!.affectedByGravity = false 
    bullet.physicsBody!.categoryBitMask = PhysicsCategories.Bullet 
    bullet.physicsBody!.collisionBitMask = PhysicsCategories.None 
    bullet.physicsBody!.contactTestBitMask = PhysicsCategories.Meteor 
    self.addChild(bullet) 

    let moveBullet = SKAction.moveToY(self.size.height + bullet.size.height, duration: 1) 
    let deleteBullet = SKAction.removeFromParent() 
    let bulletSequence = SKAction.sequence([bulletSound, moveBullet, deleteBullet]) 
    bullet.runAction(bulletSequence)   
} 

func spawnMeteor(){ 

    let randomXStart = random(min: CGRectGetMinX(gameArea), max: CGRectGetMaxX(gameArea)) 
    let randomXEnd = random(min: CGRectGetMinX(gameArea), max: CGRectGetMaxX(gameArea)) 

    let startPoint = CGPoint(x: randomXStart, y: self.size.height * 1.2) 
    let endPoint = CGPoint(x: randomXEnd, y: -self.size.height * 0.2) 

    let Meteor = SKSpriteNode(imageNamed: "Meteor\(arc4random_uniform(2))") 
    Meteor.name = "Meteor" 
    Meteor.setScale(0.2) 
    Meteor.position = startPoint 
    Meteor.zPosition = 2 
    Meteor.physicsBody = SKPhysicsBody(rectangleOfSize: meteor.size) 
    Meteor.physicsBody!.affectedByGravity = false 
    Meteor.physicsBody!.categoryBitMask = PhysicsCategories.Meteor 
    Meteor.physicsBody!.collisionBitMask = PhysicsCategories.None 
    Meteor.physicsBody!.contactTestBitMask = PhysicsCategories.Player | PhysicsCategories.Bullet 

    self.addChild(Meteor) 

    let moveMeteor = SKAction.moveTo(endPoint, duration: 2) 
    let deleteMeteor = SKAction.removeFromParent() 
    let loseALifeAction = SKAction.runBlock(loseALife) 
    let MeteorSequence = SKAction.sequence([moveMeteor, deleteMeteor, loseALifeAction]) 



    if currentGameState == gameState.inGame{ 
    Meteor.runAction(MeteorSequence) 
    } 

    let dx = endPoint.x - startPoint.x 
    let dy = endPoint.y - startPoint.y 
    let amountToRotate = atan2(dy, dx) 
    enemy.zRotation = amountToRotate 
} 


func didBeginContact(contact: SKPhysicsContact) { 

    var body1 = SKPhysicsBody() 
    var body2 = SKPhysicsBody() 


    if contact.bodyA.collisionBitMask < contact.bodyB.categoryBitMask{ 
     body1 = contact.bodyA 
     body2 = contact.bodyB 
    } 
    else{ 
     body1 = contact.bodyB 
     body2 = contact.bodyA 
    } 

    if body1.categoryBitMask == PhysicsCategories.Player && body2.categoryBitMask == PhysicsCategories.Meteor{ 
     //if the player has hit the meteor 

     if body1.node != nil { 
     spawnExplosion(body1.node!.position) 
     } 



     if body2.node != nil { 
     spawnExplosion(body2.node!.position) 
     } 


     body1.node?.removeFromParent() 
     body2.node?.removeFromParent() 


     runGameOver() 


    } 

    if body1.categoryBitMask == PhysicsCategories.Bullet && body2.categoryBitMask == PhysicsCategories.Meteor && body2.node?.position.y < self.size.height { 
     //if the bullet has hit the meteor 



     addScore() 


     if body2.node != nil{ 
     spawnExplosion(body2.node!.position) 
     spawnPlusScore(body2.node!.position) 
     } 


     body1.node?.removeFromParent() 
     body2.node?.removeFromParent() 


    } 

ответ

1

SpriteKit не выполняет точное обнаружение столкновений, поскольку он направлен на достижение более высокой производительности. Вы можете сделать свойство physicsBody в usesPreciseCollisionDetection истина, как это:

bullet.physicsBody!.usesPreciseCollisionDetection = true 

https://developer.apple.com/reference/spritekit/skphysicsbody/1520014-usesprecisecollisiondetection

Я не знаю, если это работает, пожалуйста, дайте мне знать.

+0

я добавил, но иногда я все еще могу стрелять через метеорный – EPKgames

+0

Просто упаковывают Вас интересуют , Я сталкиваюсь с аналогичной проблемой, где иногда могу снимать веревку, которую я сделал в своей игре. Я считаю, что это ошибка iOS 9.x, потому что это только начало происходить в последнее время. Установка точного столкновения также не помогла в моем случае. – crashoverride777

+0

okey tnx, что я знаю много, это не код – EPKgames

0

Вместо того чтобы устанавливать свои collisionBitMasks нулю, попробуйте установить их на это:

bullet.physicsBody!.collisionBitMask = PhysicsCategories.Meteor 
Meteor.physicsBody!.collisionBitMask = PhysicsCategories.Bullet 

И попробуйте изменить начало вашего метода didBeginContact к этому:

var body1 = contact.bodyA.node as! SKSpriteNode 
    var body2 = contact.bodyB.node as! SKSpriteNode 

if (body1.categoryBitMask == PhysicsCategories.Player && body2.categoryBitMask == PhysicsCategories.Meteor) || (body2.categoryBitMask == PhysicsCategories.Player && body1.categoryBitMask == PhysicsCategories.Meteor) { 
     //if the player has hit the meteor 
     spawnExplosion(body1.position) 
     spawnExplosion(body2.position) 

     body1.removeFromParent() 
     body2.removeFromParent() 

     runGameOver() 
    } 

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

+0

пуля больше не проходит. но теперь, если я стреляю в противника, пуля иногда отскакивает. :/ – EPKgames

+0

Что вы пытаетесь достичь, когда попали?Ваш вопрос только спросил о том, как они проходят друг друга. – claassenApps

+0

o Мне жаль, что я забыл позвонить. когда метеорит попадает правильно, метеорит взрывается и удаляется со сцены (пуля также удаляется). – EPKgames

0

Я думаю, ваша проблема находится внутри кода пули:

let moveBullet = SKAction.moveToY(self.size.height + bullet.size.height, duration: 1) 
    let deleteBullet = SKAction.removeFromParent() 
    let bulletSequence = SKAction.sequence([bulletSound, moveBullet, deleteBullet]) 
    bullet.runAction(bulletSequence) 

Попробуйте заменить bullet.physicsBody?.applyImpulse(CGVectorMake(0, 20)) вместо SKAction.moveToY и удалить пулю, если выйти с экрана

0

Я думаю, что аккуратнее способ закодировать didBeginContact является следующим образом:

func didBeginContact(contact: SKPhysicsContact) { 

    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask 

    switch contactMask 

    case PhysicsCategories.Player | PhysicsCategories.Meteor : 

     // The player and the meteor have contacted 

     spawnExplosion(contact.contactPoint) //Create explosion where they touch 
     contact.bodyA.node.removeFromParent() 
     contact.bodyB.node.removeFromParent() 
     runGameOver() 

    case PhysicsCategories.Bullet| PhysicsCategories.Meteor : 

     // The bullet and meteor have contacted 
     // body2.node?.position.y < self.size.height // ?? Not sure what this is 

     addScore() 
     spawnExplosion(contact.contactPoint) //Create explosion where they touch 
     contact.bodyA.node.removeFromParent() 
     contact.bodyB.node.removeFromParent() 

    default: 
     print("Other contact detected") 
} 

Я изменил код, чтобы создать один взрыв, где касаются 2 тел; если вы хотите 2 взрыва, каждый по центру на узлах, которые касаются, использование:

spawnExplosion(contact.bodyA.node.position) 
spawnExplosion(contact.bodyB.node.position) 

или:

for node in [contact.bodyA.node, contact.bodyB.node] { 
    spawnExplosion(node.position) 
    } 
Смежные вопросы