didBeginContact函数

时间:2015-09-12 02:57:08

标签: swift sprite-kit

我有一个游戏,主角通过按下屏幕按钮向敌人(当前是炸弹)发射子弹,并试图避免掉落物体。目前我一次射击一颗甚至几颗子弹都没有问题。但是,在测试时,如果我一次拍摄一组(20到50之间),我会收到上述错误。有没有人有什么建议?我不知道为什么我的任何节点都是零。我怀疑我的子弹在退出屏幕时实际上并没有被移除,但这可能是一个不同的问题。

以下是获取错误的行:

func didBeginContact(contact: SKPhysicsContact) {


let firstNode = contact.bodyA.node as! SKSpriteNode
let secondNode = contact.bodyB.node as! SKSpriteNode - fatal error: unexpectedly found nil while unwrapping an Optional value

完整代码:

import SpriteKit
import CoreMotion


class GameScene: SKScene, SKPhysicsContactDelegate {

let joyStickSprite = SKSpriteNode(imageNamed: "flatLight09")
let leftButton = SKSpriteNode (imageNamed: "flatLight03")
let rightButton = SKSpriteNode (imageNamed: "flatLight04")
let jumpButton = SKSpriteNode (imageNamed: "flatLight24")
let fireButton = SKSpriteNode (imageNamed: "flatLight47")

let playerSprite = SKSpriteNode(imageNamed: "p3_front")
let enemySprite = SKSpriteNode(imageNamed: "bomb")
let bomb = SKSpriteNode(imageNamed: "bomb")
let floorSprite = SKSpriteNode(imageNamed: "floorGrass")
var coinSprite = SKSpriteNode(imageNamed: "gold_1")
var left = false
var right = false

var bullet: SKNode!

var motionManager = CMMotionManager()
var destY:CGFloat  = 0.0

var scoreLabel: SKLabelNode!
var score = 0

var coinOnScreen = false

var explosion : SKSpriteNode!
var groundExplosionFrames : [SKTexture]!


struct CollisionCategoryBitmask {
    static let Player: UInt32 = 0x1 << 0
    static let Enemy: UInt32 = 0x1 << 1
    static let Floor: UInt32 = 0x1 << 2
    static let Coin: UInt32 = 0x1 << 3
    static let bomb: UInt32 = 0x1 << 4
    static let bullet: UInt32 = 0x1 << 5
}

var background = SKSpriteNode(imageNamed: "blue_land")

override func didMoveToView(view: SKView) {

    self.physicsWorld.contactDelegate = self


    createBackground()
    createPlayer()

    createFloor()
    createJoyStick()
    createJumpButton()
    createFireButton()
    setUpLabels()

    dropEnemy()


    var wait3 = SKAction.waitForDuration(1.0)
    var run3 = SKAction.runBlock {
        self.bomb.removeFromParent()
        self.createBomb()

    }
    self.runAction(SKAction.repeatActionForever(SKAction.sequence([wait3, run3])))


    /*
    var wait = SKAction.waitForDuration(5, withRange: 3)
    var run = SKAction.runBlock {
       self.coinSprite.removeFromParent()
       self.createCoins()
    }
    self.runAction(SKAction.repeatActionForever(SKAction.sequence([wait, run])))
    */


    //Load the TextureAtlas for the bear
    let groundExplosianAnimatedAtlas : SKTextureAtlas = SKTextureAtlas(named: "GroundExplosion")

    //Load the animation frames from the TextureAtlas
    var explodeFrames = [SKTexture]()
    let numImages : Int = groundExplosianAnimatedAtlas.textureNames.count
    for var i=1; i<=numImages/2; i++ {
        let explosionTextureName = "groundExplosion0\(i)"
        explodeFrames.append(groundExplosianAnimatedAtlas.textureNamed(explosionTextureName))
    }

    groundExplosionFrames = explodeFrames

    motionManager.accelerometerUpdateInterval = 0.1
    motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.currentQueue()) {
        [unowned self] accelerometerData, error in

        var currentY = self.enemySprite.position.y
        let acceleration = accelerometerData.acceleration
        self.destY = (CGFloat(acceleration.y) * 0.75) + (self.destY * 0.25)
        }
    }

override func willMoveFromView(view: SKView) {
    motionManager.stopAccelerometerUpdates()

    removeAllChildren()
}

func groundExplosion() {

    var explode = SKAction.runBlock({

        self.enemySprite.runAction( SKAction.repeatAction(SKAction.animateWithTextures(self.groundExplosionFrames, timePerFrame: 0.05, resize: false, restore: true), count: 1), withKey:"groundExplosion")
        self.enemySprite.physicsBody?.dynamic = false

        })

    var wait = SKAction.waitForDuration(0.2)

    var remove = SKAction.runBlock({self.enemySprite.removeFromParent()})

    var drop = SKAction.runBlock({self.createEnemy()})

    var sequence = SKAction.sequence([explode, wait, remove, drop])

    self.runAction(sequence)

}

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


    for touch in (touches as! Set<UITouch>) {
        let location = touch.locationInNode(self)

        let touchedNode = self.nodeAtPoint(location)

        if let name = touchedNode.name
        {
            if name == "joyStick"
            {

                if location.x < joyStickSprite.position.x {
                    left = true
                    right = false
                }

                else {
                    right = true
                    left = false
                }
            }
        }

        if let name = touchedNode.name
        {
            if name == "jumpButton"
            {
                if playerSprite.position.y < 100 {
                    self.playerSprite.physicsBody?.applyImpulse(CGVector(dx: 0.0, dy: 60.0))

                }

            }

            if name == "fireButton"
            {

                makeBullet()

            }
        }



    }

}

override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {

    left = false
    right = false
    playerSprite.texture = SKTexture(imageNamed: "p3_front")


}

func setUpLabels () {
    //set up labels

    scoreLabel = SKLabelNode(fontNamed: "Arial")
    scoreLabel.position = CGPoint(x: self.size.width/10, y: self.size.height - 30)
    scoreLabel.text = String("Score \(score)")
    scoreLabel.fontColor = UIColor.grayColor()
    scoreLabel.fontSize = 35
    self.addChild(scoreLabel)


}

func createBackground () {

    background.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
    background.size.height = self.size.height

    addChild(background)

}

func createPlayer () {

    playerSprite.position = CGPoint(x: self.size.width / 2, y: floorSprite.size.height/2)
    playerSprite.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(playerSprite.size.width/2.5, playerSprite.size.height))
    playerSprite.physicsBody?.dynamic = true
    playerSprite.physicsBody?.allowsRotation = false
    playerSprite.physicsBody?.friction = 100.0
    playerSprite.physicsBody?.affectedByGravity = true
    playerSprite.physicsBody?.categoryBitMask = CollisionCategoryBitmask.Player
    playerSprite.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Floor
    playerSprite.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.Enemy | CollisionCategoryBitmask.Coin | CollisionCategoryBitmask.bomb


    addChild(playerSprite)

}

func movePlayerLeft () {
    let moveLeft = SKAction.moveByX(-8, y: 0, duration: 0.5)
    playerSprite.runAction(moveLeft)

}

func movePlayerRight () {
    let moveRight = SKAction.moveByX(8, y: 0, duration: 0.5)
    playerSprite.runAction(moveRight)
}

func makeBullet() {

    var bullet = SKSpriteNode(imageNamed: "laserBlue01")

    bullet.position = CGPointMake(playerSprite.position.x, playerSprite.position.y - 20)
    bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.size)
    bullet.physicsBody?.dynamic = true
    bullet.physicsBody?.affectedByGravity = false
    bullet.physicsBody?.categoryBitMask = CollisionCategoryBitmask.bullet
    bullet.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.bomb | CollisionCategoryBitmask.Enemy
    bullet.physicsBody?.collisionBitMask = 0

    var movebullet = SKAction.moveByX(CGFloat (-400), y: 0, duration: 1)
    var movebulletForever = SKAction.repeatActionForever(movebullet)
    bullet.runAction(movebulletForever)

    self.addChild(bullet)
}

func createEnemy () {

    enemySprite.removeFromParent()

    var randomX = Int(arc4random_uniform(600))
    var randomXCG = CGFloat(randomX)

    enemySprite.size.height = playerSprite.size.height/2
    enemySprite.size.width = enemySprite.size.height
    enemySprite.position = CGPoint(x: randomXCG, y: self.size.height - enemySprite.size.height/2)
    enemySprite.physicsBody = SKPhysicsBody(circleOfRadius: enemySprite.size.width / 2)
    enemySprite.physicsBody?.dynamic = false
    enemySprite.physicsBody?.allowsRotation = false
    enemySprite.physicsBody?.restitution = 0.0
    enemySprite.physicsBody?.friction = 0.8
    enemySprite.physicsBody?.angularDamping = 0.0
    enemySprite.physicsBody?.linearDamping = 0.0
    enemySprite.physicsBody?.affectedByGravity = false

    enemySprite.physicsBody?.categoryBitMask = CollisionCategoryBitmask.Enemy
    enemySprite.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Floor

    addChild(enemySprite)
}

func createBomb () {

    bomb.removeFromParent()

    var randomX = Int(arc4random_uniform(600))
    var randomXCG = CGFloat(randomX)

    bomb.size.height = playerSprite.size.height/2
    bomb.size.width = bomb.size.height
    bomb.position = CGPoint(x: randomXCG, y: self.size.height - bomb.size.height/2)
    bomb.physicsBody = SKPhysicsBody(circleOfRadius: bomb.size.width / 2)
    bomb.physicsBody?.dynamic = true
    bomb.physicsBody?.allowsRotation = false
    bomb.physicsBody?.restitution = 0.0
    bomb.physicsBody?.friction = 10.0
    bomb.physicsBody?.angularDamping = 0.0
    bomb.physicsBody?.linearDamping = 0.0
    bomb.physicsBody?.affectedByGravity = true

    bomb.physicsBody?.categoryBitMask = CollisionCategoryBitmask.bomb
    bomb.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Floor
    bomb.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.Coin

    addChild(bomb)
}

func dropEnemy () {

    self.enemySprite.removeFromParent()

    var wait2 = SKAction.waitForDuration(0.0)
    var run2 = SKAction.runBlock {
        self.enemySprite.physicsBody?.dynamic = true
        self.enemySprite.physicsBody?.affectedByGravity = true

    }

    createEnemy()
    self.runAction(SKAction.repeatActionForever(SKAction.sequence([wait2, run2])))

}

func createCoins () {

    coinOnScreen = true

    var randomX = Int(arc4random_uniform(600))
    var randomXCG = CGFloat(randomX)

    coinSprite.size.height = playerSprite.size.height/2
    coinSprite.size.width = coinSprite.size.height
    coinSprite.position = CGPoint(x: randomXCG, y: self.size.height - coinSprite.size.height/2)
    coinSprite.physicsBody = SKPhysicsBody(circleOfRadius: coinSprite.size.width/2)
    coinSprite.physicsBody?.dynamic = true
    coinSprite.physicsBody?.affectedByGravity = true
    coinSprite.physicsBody?.categoryBitMask = CollisionCategoryBitmask.Coin
    coinSprite.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.Enemy | CollisionCategoryBitmask.bomb
    coinSprite.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Floor

    addChild(coinSprite)
}

func createJoyStick () {

    joyStickSprite.setScale(0.9)
    joyStickSprite.position = CGPoint(x: self.size.width/1.1, y: joyStickSprite.size.height)
    joyStickSprite.name = "joyStick"
    joyStickSprite.userInteractionEnabled = false
    joyStickSprite.alpha = 0.0

    leftButton.setScale(0.8)
    leftButton.position = CGPoint (x: joyStickSprite.position.x - 30, y: joyStickSprite.size.height)

    rightButton.setScale(0.8)
    rightButton.position = CGPoint (x: joyStickSprite.position.x + 30 , y: joyStickSprite.size.height)

    addChild(leftButton)
    addChild(rightButton)
    addChild(joyStickSprite)
}

func createJumpButton () {
    jumpButton.position = CGPoint (x: 30, y: joyStickSprite.size.height)
    jumpButton.setScale(0.6)
    jumpButton.name = "jumpButton"
    addChild(jumpButton)
}

func createFireButton () {
    fireButton.position = CGPoint (x: 70, y: joyStickSprite.size.height-50)
    fireButton.setScale(0.6)
    fireButton.name = "fireButton"
    addChild(fireButton)
}

func updateCoinPosition () {


    coinSprite.position.x =  coinSprite.position.x + destY*20


}

func didBeginContact(contact: SKPhysicsContact) {


    let firstNode = contact.bodyA.node as! SKSpriteNode
    let secondNode = contact.bodyB.node as! SKSpriteNode

    if (contact.bodyA.categoryBitMask == CollisionCategoryBitmask.Player) &&
        (contact.bodyB.categoryBitMask == CollisionCategoryBitmask.Enemy) {

            let transition = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1.0)

            let scene = SecondScene(size: self.scene!.size)
            scene.scaleMode = SKSceneScaleMode.AspectFill

            self.scene!.view!.presentScene(scene, transition: transition)
            }

    if (contact.bodyA.categoryBitMask == CollisionCategoryBitmask.Player) &&
        (contact.bodyB.categoryBitMask == CollisionCategoryBitmask.bomb) {

            let transition = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1.0)

            let scene = SecondScene(size: self.scene!.size)
            scene.scaleMode = SKSceneScaleMode.AspectFill

            self.scene!.view!.presentScene(scene, transition: transition)
    }



    if (contact.bodyA.categoryBitMask == CollisionCategoryBitmask.Player) &&
        (contact.bodyB.categoryBitMask == CollisionCategoryBitmask.Coin) {

            coinOnScreen = false
            self.coinSprite.removeFromParent()
            score += 5
            scoreLabel.text = String("Score \(score)")

    }

    if (contact.bodyA.categoryBitMask == CollisionCategoryBitmask.Enemy) &&
        (contact.bodyB.categoryBitMask == CollisionCategoryBitmask.Coin) {

            groundExplosion()
            coinSprite.removeFromParent()
            coinOnScreen = false


    }

    if (contact.bodyA.categoryBitMask == CollisionCategoryBitmask.Coin) &&
        (contact.bodyB.categoryBitMask == CollisionCategoryBitmask.bomb) {

            bomb.removeFromParent()
            coinSprite.removeFromParent()
            coinOnScreen = false
    }

    if (contact.bodyA.categoryBitMask == CollisionCategoryBitmask.bomb) &&
        (contact.bodyB.categoryBitMask == CollisionCategoryBitmask.Coin) {

            bomb.removeFromParent()
            coinSprite.removeFromParent()
            coinOnScreen = false
    }

    if (contact.bodyA.categoryBitMask == CollisionCategoryBitmask.Floor) &&
        (contact.bodyB.categoryBitMask == CollisionCategoryBitmask.Coin) {

            var wait5 = SKAction.waitForDuration(1.5)

            var fadeOut = SKAction.fadeAlphaTo(0.2, duration: 0.3)
            var fadeIn = SKAction.fadeAlphaTo(1.0, duration: 0.3)


            coinSprite.runAction(SKAction.repeatAction(SKAction.sequence([ wait5, fadeOut, fadeIn, fadeOut, fadeIn, fadeOut, fadeIn ]), count: 1), completion : {
                    self.coinSprite.removeFromParent()
                    self.coinOnScreen = false

                })

    }

    if (contact.bodyA.categoryBitMask == CollisionCategoryBitmask.bullet) &&
        (contact.bodyB.categoryBitMask == CollisionCategoryBitmask.Enemy)
    {

            var bullet1 = contact.bodyA.node

            score += 1
            scoreLabel.text = String("Score \(score)")

            bullet1!.removeFromParent()
            enemySprite.removeFromParent()

            dropEnemy()

    }

    if (contact.bodyA.categoryBitMask == CollisionCategoryBitmask.bullet) &&
        (contact.bodyB.categoryBitMask == CollisionCategoryBitmask.bomb )
    {

        var bullet1 = contact.bodyA.node
        var bombEnemy = contact.bodyB.node

        score += 1
        scoreLabel.text = String("Score \(score)")

        bullet1!.removeFromParent()
        bombEnemy?.removeFromParent()


    }
}

func createFloor () {

    floorSprite.position = CGPoint(x: self.size.width/2, y: 0)
    floorSprite.setScale(0.50)
    floorSprite.physicsBody = SKPhysicsBody(edgeFromPoint: CGPointMake( -self.size.width, floorSprite.size.height/2), toPoint: CGPointMake(self.size.width, floorSprite.size.height/2 ))
    floorSprite.physicsBody?.dynamic = false
    floorSprite.physicsBody?.categoryBitMask = CollisionCategoryBitmask.Floor
    floorSprite.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Enemy
    floorSprite.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.Enemy | CollisionCategoryBitmask.Coin

    addChild(floorSprite)
}

override func update(currentTime: CFTimeInterval) {

    //detect where on joystick player is touching
    if left == true {
        playerSprite.texture = SKTexture(imageNamed: "alienPink_swim3")
        movePlayerLeft()
    }

    if right == true {
        movePlayerRight()
        playerSprite.texture = SKTexture(imageNamed: "alienPink_swim1")
    }

    //move player to other side when going off screen
    if playerSprite.position.x < -20.0 {
        playerSprite.position = CGPoint(x: self.size.width + 20.0, y: playerSprite.position.y)
    } else if (playerSprite.position.x > self.size.width + 20.0) {
        playerSprite.position = CGPoint(x: -20.0, y: playerSprite.position.y)
    }


    if coinOnScreen == true {
        //remove coin if off screen
        if coinSprite.position.x < -20.0 || coinSprite.position.x > self.size.width + 20.0 {
            self.coinSprite.removeFromParent()
            coinOnScreen = false
        }
    }


    //remove bullet if off screen
    if bullet?.position.x < -20.0 || bullet?.position.x > self.size.width + 20.0 {
        self.bullet?.removeFromParent()
    }

    if coinSprite.position.y < floorSprite.size.height {

        updateCoinPosition()
    }



}

}

有什么建议吗?

0 个答案:

没有答案
相关问题