2016-06-28 61 views
0

我正在使用sprite套件(2D)進行遊戲。當我在敵人身上射擊時,有時候子彈會穿過敵人,我該如何解決這個問題?

我有這樣的代碼:

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

和我有你需要摧毀,但有時當我拍我的設備上的流星子彈穿過流星 流星形象是這樣的一個bug或我做錯什麼了嗎? 和 我該如何解決這個問題?

感謝您閱讀我的問題,希望有人能幫助我! 如果你不明白我的問題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爲true,像這樣:

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) 
    }