小行星对战游戏继续崩溃

时间:2016-01-29 12:58:52

标签: ios sprite-kit swift2

因此我在游戏过程中随机时间不断收到此错误,并且#34;致命错误:在解开可选值时意外发现nil"在我的小行星战斗游戏中。我会在这里发布代码,如果有人能帮我解决,我会很感激。如果您不了解任何可以问我的部分

import SpriteKit
import Darwin

struct PhysicsCatagory {
    static let Asteroids : UInt32 = 1 //00000000000000000000000000000001
    static let Bullet : UInt32 = 2 //0000000000000000000000000000010
    static let Fighter : UInt32 = 3 //0000000000000000000000000000100

    }

class GameScene: SKScene, SKPhysicsContactDelegate {

var Score = Int()
var scoreLabel = UILabel()

var Fighter = SKSpriteNode(imageNamed: "Fighter")

override func didMoveToView(view: SKView) {
    /* Setup your scene here */

    physicsWorld.contactDelegate = self

    Fighter.position = CGPointMake(self.size.width / 2, self.size.height / 7)
    Fighter.physicsBody = SKPhysicsBody(rectangleOfSize: Fighter.size)
    Fighter.physicsBody?.affectedByGravity = false
    Fighter.physicsBody?.categoryBitMask = PhysicsCatagory.Fighter
    Fighter.physicsBody?.contactTestBitMask = PhysicsCatagory.Asteroids
    Fighter.physicsBody?.dynamic = false

    var Timer = NSTimer.scheduledTimerWithTimeInterval(0.25, target: self, selector: Selector("spawnBullets"), userInfo: nil, repeats: true)

    var asteriodsTimer = NSTimer.scheduledTimerWithTimeInterval(0.35 , target: self, selector: Selector("spawnAsteroids"), userInfo: nil, repeats: true)

    var furiousAsteriodsTimer = NSTimer.scheduledTimerWithTimeInterval(0.9 , target: self, selector: Selector("spawnFuriousAsteroids"), userInfo: nil, repeats: true)


    self.addChild(Fighter)

    scoreLabel.text = "\(Score)"
    scoreLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
    scoreLabel.backgroundColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 0.3)
    scoreLabel.textColor = UIColor.whiteColor()

    self.view?.addSubview(scoreLabel)

}

func didBeginContact(contact: SKPhysicsContact) {

    let firstBody : SKPhysicsBody = contact.bodyA
    let secondBody : SKPhysicsBody = contact.bodyB

    if ((firstBody.categoryBitMask == PhysicsCatagory.Asteroids) && (secondBody.categoryBitMask == PhysicsCatagory.Bullet) || (firstBody.categoryBitMask == PhysicsCatagory.Bullet) && (secondBody.categoryBitMask == PhysicsCatagory.Asteroids)){

        bulletHitAsteroids(firstBody.node as! SKSpriteNode, Bullet: secondBody.node as! SKSpriteNode)

    }
}

func bulletHitAsteroids(Asteroids: SKSpriteNode, Bullet: SKSpriteNode){

    Asteroids.removeFromParent()
    Bullet.removeFromParent()

    Score++
    scoreLabel.text = "\(Score)"

}

func bulletHitFuriousAsteroids(FuriousAsteroids: SKSpriteNode, Bullet: SKSpriteNode){

    FuriousAsteroids.removeFromParent()
    Bullet.removeFromParent()

    Score = Score + 2
    scoreLabel.text = "\(Score)"
}


func spawnBullets(){

    let Bullet = SKSpriteNode(imageNamed: "Bullet")
    Bullet.zPosition = -5
    Bullet.position = CGPointMake(Fighter.position.x, Fighter.position.y)

    let action = SKAction.moveToY(self.size.height + 30, duration: 0.9)
    let actionDone = SKAction.removeFromParent()
    Bullet.runAction(SKAction.sequence([action, actionDone]))

    Bullet.physicsBody = SKPhysicsBody(rectangleOfSize: Bullet.size)
    Bullet.physicsBody?.categoryBitMask = PhysicsCatagory.Bullet
    Bullet.physicsBody?.contactTestBitMask = PhysicsCatagory.Asteroids
    Bullet.physicsBody?.affectedByGravity = false
    Bullet.physicsBody?.dynamic = false

    self.addChild(Bullet)

}



func spawnAsteroids(){
    let Asteroids = SKSpriteNode(imageNamed: "Asteroid")
    let minValue = self.size.width / 8
    let maxValue = self.size.width - 20
    let spawnPoint = UInt32(maxValue - minValue)
    Asteroids.position = CGPoint(x: CGFloat(arc4random_uniform(spawnPoint)) , y: self.size.height)

    Asteroids.physicsBody = SKPhysicsBody(rectangleOfSize: Asteroids.size)
    Asteroids.physicsBody?.categoryBitMask = PhysicsCatagory.Asteroids
    Asteroids.physicsBody?.contactTestBitMask = PhysicsCatagory.Bullet
    Asteroids.physicsBody?.affectedByGravity = false
    Asteroids.physicsBody?.dynamic = true


    let action = SKAction.moveToY(-50, duration: 2.5)
    let actionDone = SKAction.removeFromParent()

    Asteroids.runAction(SKAction.sequence([action, actionDone]))

    self.addChild(Asteroids)

}

func spawnFuriousAsteroids(){
    let FuriousAsteroids = SKSpriteNode(imageNamed: "FuriousAsteroid")
    let minValue = self.size.width / 8
    let maxValue = self.size.width - 20
    let spawnPoint = UInt32(maxValue - minValue)
    FuriousAsteroids.position = CGPoint(x: CGFloat(arc4random_uniform(spawnPoint)) , y: self.size.height)

    FuriousAsteroids.physicsBody = SKPhysicsBody(rectangleOfSize: FuriousAsteroids.size)
    FuriousAsteroids.physicsBody?.categoryBitMask = PhysicsCatagory.Asteroids
    FuriousAsteroids.physicsBody?.contactTestBitMask = PhysicsCatagory.Bullet
    FuriousAsteroids.physicsBody?.affectedByGravity = false
    FuriousAsteroids.physicsBody?.dynamic = true


    let action = SKAction.moveToY(-50, duration: 1.5)
    let actionDone = SKAction.removeFromParent()

    FuriousAsteroids.runAction(SKAction.sequence([action, actionDone]))

    self.addChild(FuriousAsteroids)

}


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   /* Called when a touch begins */

    for touch in touches {
        let location = touch.locationInNode(self)

        Fighter.position.x = location.x
    }
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

    for touch in touches {
        let location = touch.locationInNode(self)

        Fighter.position.x = location.x
    }
}

override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */
}
}

1 个答案:

答案 0 :(得分:0)

它崩溃了,因为其中一个实体没有它的节点。发生崩溃时,请尝试在调试器控制台中输入类似的内容:

po firstBody.nodepo secondBody.node。其中一个将是nil

如果您的示例中有两个以上的实体进行接触,则会发生这种情况,您可能会遇到子弹和两个小行星可能同时处于联系状态的情况。因为SpriteKit当时只能检查两个物体之间的接触,所以会发生这样的事情:

    传入
  • didBeginContact时传入两个物理实体(子弹和第一个星体)
  • 现在,你强行展开与这些尸体相关的节点并从其父级移除小行星和子弹

然后,因为发生了更多的联系

    再次使用另外两个物理实体调用
  • didBeginContact,但其中一个物理实体再次是子弹的物理实体。另一个身体,就是愤怒的小行星。
  • 现在,你再次强行解开与这两个物理体相关的节点,但其中一个(子弹)是零。

在您的didBeginContact方法中,解决方案会是这样的:

 if let firstNode = firstBody.node as? SKSpriteNode, let secondNode = secondBody.node as? SKSpriteNode {

   bulletHitAsteroids(firstNode, Bullet: secondNode)
}

这样,一枚子弹只能摧毁一颗小行星。我猜你想要什么,毕竟有什么意义。