应用程序不断崩溃,由于未捕获的异常'NSInvalidArgumentException'终止应用程序

时间:2015-07-13 05:30:13

标签: ios swift game-physics

我正在制作一个游戏,其中随机物体落入随机位置,并且有一个固定y轴的球并且沿着x轴保持移动,并且它必须移动投掷物体,我试图计算分数和我这样做的方式是我创建了一个物理对象,它与球在同一个y轴上,当对象碰撞时,应该调用分数函数并将分数增加1,但由于某种原因该应用程序不断崩溃,它给了我这个错误。

2015-07-13 01:23:17.242 WalkRun[26792:3773366] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already has a parent: <SKSpriteNode> name:'(null)' texture:[<SKTexture> 'shortwall' (60 x 60)] position:{30, 768} size:{60, 60} rotation:0.00'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001073c33f5 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x00000001092eabb7 objc_exception_throw + 45
    2   CoreFoundation                      0x00000001073c332d +[NSException raise:format:] + 205
    3   SpriteKit                           0x0000000107ebfaf6 -[SKNode addChild:] + 111
    4   WalkRun                             0x00000001071c8c44 _TFC7WalkRun9PlayScene10leftObjectfS0_FT_T_ + 2868
    5   WalkRun                             0x00000001071c7ddc _TFC7WalkRun9PlayScene10randObjectfS0_FT_T_ + 236
    6   WalkRun                             0x00000001071c8102 _TToFC7WalkRun9PlayScene10randObjectfS0_FT_T_ + 34
    7   Foundation                          0x0000000107a39fd4 __NSFireTimer + 83
    8   CoreFoundation                      0x000000010732b4e4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    9   CoreFoundation                      0x000000010732b0a5 __CFRunLoopDoTimer + 1045
    10  CoreFoundation                      0x00000001072ee3dd __CFRunLoopRun + 1901
    11  CoreFoundation                      0x00000001072eda06 CFRunLoopRunSpecific + 470
    12  GraphicsServices                    0x000000010e7569f0 GSEventRunModal + 161
    13  UIKit                               0x0000000108046550 UIApplicationMain + 1282
    14  WalkRun                             0x00000001071d54ce top_level_code + 78
    15  WalkRun                             0x00000001071d550a main + 42
    16  libdyld.dylib                       0x0000000109ad9145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

这是我的代码:

//
//  PlayScene.swift
//  WalkRun
//
//  Created by naeim on 7/10/15.
//  Copyright (c) 2015 naeim. All rights reserved.
//

import Foundation
import SpriteKit

class PlayScene: SKScene, SKPhysicsContactDelegate{

    var ball = SKSpriteNode(imageNamed: "ball")
    var wall = SKNode()
    var wallRight = SKNode()
    var wallMiddle = SKNode()
    var ballSpeed = CGFloat()

    var bigWall = SKSpriteNode(imageNamed: "shortwall")
    var tallWall = SKSpriteNode(imageNamed: "tallwall")

    var ballGroup:UInt32 = 1
    var objectGroup:UInt32 = 2
    var gapGroup:UInt32 = 3

    var gameOver = 0

    var movingObjects = SKNode()

    var score = 0
    var scoreLabel = SKLabelNode()

    override func didMoveToView(view: SKView) {

        self.physicsWorld.contactDelegate = self

        backgroundColor = UIColor(hex: 0x80d9ff)
        self.physicsWorld.gravity = CGVectorMake(-9,0)

        self.addChild(movingObjects)

        //creating the ball
        ball.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMinY(self.frame) + self.ball.size.height * 2)
        ball.physicsBody = SKPhysicsBody(circleOfRadius: self.ball.size.width / 2)
        ball.zPosition = 10


        //let the ball rotate forever
        ballSpeed = 3
        let rotateAction = SKAction.rotateByAngle(ballSpeed, duration: 1)
        let repeatAction = SKAction.repeatActionForever(rotateAction)
        ball.runAction(repeatAction)
        ball.physicsBody?.categoryBitMask = ballGroup
        ball.physicsBody?.collisionBitMask = objectGroup
        ball.physicsBody?.contactTestBitMask = objectGroup

        self.addChild(ball)

        //creating the wall of the left
        wall.position = CGPointMake(CGRectGetMinX(self.frame),CGRectGetMinY(self.frame))
        wall.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, self.frame.size.height * 2.0))
        wall.physicsBody?.dynamic = false
        wall.physicsBody?.categoryBitMask = objectGroup
        self.addChild(wall)

        //creating the wall of the right
        wallRight.position = CGPointMake(CGRectGetMaxX(self.frame), CGRectGetMinY(self.frame))
        wallRight.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, self.frame.size.height * 2.0))
        wallRight.physicsBody?.dynamic = false
        wallRight.physicsBody?.categoryBitMask = objectGroup
        self.addChild(wallRight)

        //creating the middle wall that objects pass by
        wallMiddle.position = CGPointMake(CGRectGetMinX(self.frame), CGRectGetMinY(self.frame))
        wallMiddle.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, 1))
        wallMiddle.physicsBody?.dynamic = false
        wallMiddle.physicsBody?.categoryBitMask = gapGroup
        wallMiddle.physicsBody?.collisionBitMask = gapGroup
        wallMiddle.physicsBody?.contactTestBitMask = objectGroup
        self.addChild(wallMiddle)

        //creating the label
        scoreLabel.fontName = "Helvetica"
        scoreLabel.fontSize = 60
        scoreLabel.text = "0"
        scoreLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 70 )
        self.addChild(scoreLabel)

        var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("randObject"), userInfo: nil, repeats: true)

        var timerObjects = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("checkObjectPlace"), userInfo: nil, repeats: true)


    }

    func checkObjectPlace(){



    }

    //function to randomly choose which object

    func randObject(){
        if gameOver == 0{

        var rand = arc4random_uniform(6)+1

        switch(rand){

        case 1:
            leftObject()
        case 2:
            middleObject()
        case 3:
            rightObject()
        case 4:
            LeftAndMiddleObject()
        case 5:
            rightAndLeftObject()
        case 6:
            rightAndMiddleObject()
        default:
            println("error !! non a number other than 0, 1, 2 has been choosen .")

            }

        }
    }

    //function to create the left objects

    func leftObject(){
        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {

             bigWall.position = CGPointMake(CGRectGetMinX(self.frame) + bigWall.size.width / 2, CGRectGetMaxY(self.frame))

            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            bigWall.runAction(moveAndRemoveObjects)
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup

            movingObjects.addChild(bigWall)

        }
        else
        {

            tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            tallWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false

            tallWall.physicsBody?.categoryBitMask = objectGroup


            movingObjects.addChild(tallWall)
        }


    }

    //function to create the middle objects

    func middleObject(){

        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            bigWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            bigWall.runAction(moveAndRemoveObjects)
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(bigWall)
        }
        else
        {
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            tallWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            tallWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
        }

    }

    //function to create the right objects

    func rightObject(){
        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            bigWall.runAction(moveAndRemoveObjects)
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(bigWall)

        }
        else
        {
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            tallWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)

            if ball.position.x == tallWall.position.x{
                scoreIncrement()
            }
        }


    }

    //function to create a right and left object

    func rightAndLeftObject(){

        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            bigWall.runAction(moveAndRemoveObjects)
            tallWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
             movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)

                        bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
        }
        else
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
            tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            tallWall.runAction(moveAndRemoveObjects)
            bigWall.runAction(moveAndRemoveObjects)
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)
        }


    }

    func rightAndMiddleObject(){

        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            bigWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))

            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])

            tallWall.runAction(moveAndRemoveObjects)
            bigWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)

        }
        else
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            bigWall.position = CGPointMake(CGRectGetMidX(self.frame) , CGRectGetMaxY(self.frame))
            tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])

            tallWall.runAction(moveAndRemoveObjects)
            bigWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)
        }


    }

    func LeftAndMiddleObject(){

        var rand = arc4random_uniform(2) + 1
        if rand == 1
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))
            bigWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))

            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])

            tallWall.runAction(moveAndRemoveObjects)
            bigWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)

        }
        else
        {
            var bigWall = SKSpriteNode(imageNamed: "shortwall")
            var tallWall = SKSpriteNode(imageNamed: "tallwall")
            bigWall.position = CGPointMake(CGRectGetMidX(self.frame) , CGRectGetMaxY(self.frame))
            tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))

            var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
            var removeObjects = SKAction.removeFromParent()
            var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])

            tallWall.runAction(moveAndRemoveObjects)
            bigWall.runAction(moveAndRemoveObjects)
            tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
            tallWall.physicsBody?.dynamic = false
            bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
            bigWall.physicsBody?.dynamic = false
            bigWall.physicsBody?.categoryBitMask = objectGroup
            tallWall.physicsBody?.categoryBitMask = objectGroup
            movingObjects.addChild(tallWall)
            movingObjects.addChild(bigWall)
        }


    }

    func scoreIncrement(){

        score = score + 1
       scoreLabel.text = "\(score)"
    }


    func didBeginContact(contact: SKPhysicsContact) {

        println("contact")

        if  contact.bodyA.categoryBitMask == gapGroup || contact.bodyB.categoryBitMask == gapGroup {

            println("gap contact")

        } else {

            gameOver = 1
            movingObjects.speed = 0

        }
    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        if gameOver == 0 {

        ball.physicsBody?.velocity = CGVectorMake(0, 0)
        ball.physicsBody?.applyImpulse(CGVectorMake(70,0))

        }

    }

    override func update(currentTime: NSTimeInterval) {



    }
}

2 个答案:

答案 0 :(得分:0)

该错误表明您正在尝试将子节点添加到已有父节点的节点。堆栈跟踪指向leftObject方法。在这里,您有一个SKAction设置,可以在一段时间内移动,然后从父项中删除。

        var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
        var removeObjects = SKAction.removeFromParent()
        var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
        bigWall.runAction(moveAndRemoveObjects)

这会将操作添加到节点并运行,但您的代码路径将继续下去

    movingObjects.addChild(bigWall)

几乎立刻。看起来像竞争条件,您认为代码将等到操作完成后再继续运行。

答案 1 :(得分:0)

您有一个名为bigWall的实例属性,在大多数方法中,您创建一个名为bigWall的本地对象并将其添加到场景中。因为每次调用方法时它都是一个新对象,所以它工作正常。但是在方法leftObject中,您没有本地对象bigWall,因此它引用了实例属性。第一次调用leftObject时,可以将实例属性bigWall添加到场景中。第二次调用方法时,它会尝试将bigWall实例属性添加到场景中,当场景已经存在于场景中时,您将获得错误。