Xcode 7.3:"线程1:EXC_BAD_ACCESS(代码= 1,地址= 0x0)"

时间:2016-07-03 16:39:52

标签: xcode swift multithreading sprite-kit crash

以下是关于我的项目的一些信息:它是我买的book的项目 这是我的代码:

import SpriteKit
import CoreMotion
import GameplayKit

struct PhysicsCategory {
static let None: UInt32              = 0
static let Player: UInt32            = 0b1       // 1
static let PlatformNormal: UInt32    = 0b10      // 2
static let PlatformBreakable: UInt32 = 0b100     // 4
static let CoinNormal: UInt32        = 0b1000    // 8
static let CoinSpecial: UInt32       = 0b10000   // 16
static let Edges: UInt32             = 0b100000  // 32
static let PlatformDead: UInt32      = 0b1000000 // 64
}

class GameScene: SKScene, SKPhysicsContactDelegate {

var bgNode = SKNode()
var fgNode = SKNode()
var background: SKNode!
var lava: SKSpriteNode!
var backHeight: CGFloat = 0.0
var player: SKSpriteNode!
let motionManager = CMMotionManager()
let cameraNode = SKCameraNode()

// platforms (14)
var platform5Across: SKSpriteNode!
var coinArrow: SKSpriteNode!
var platformArrow: SKSpriteNode!
var platformDiagonal: SKSpriteNode!
var breakArrow: SKSpriteNode!
var break5Across: SKSpriteNode!
var breakDiagonal: SKSpriteNode!
var coin5Across: SKSpriteNode!
var coinDiagonal: SKSpriteNode!
var coinCross: SKSpriteNode!
var coinS5Across: SKSpriteNode!
var coinSDiagonal: SKSpriteNode!
var coinSCross: SKSpriteNode!
var coinSArrow: SKSpriteNode!
var platformMove: SKSpriteNode!
var enemyPlatform: SKSpriteNode!

var lastItemPosition = CGPointZero
var lastItemHeight: CGFloat = 0.0
var levelY: CGFloat = 0.0
var isPlaying: Bool = false
var xAcceleration = CGFloat(0)
var lastUpdateTimeInterval: NSTimeInterval = 0
var deltaTime: NSTimeInterval = 0
var lerpValue = CGFloat(0.2)

let cNa = SKAction.playSoundFileNamed("coin1", waitForCompletion:     false)
let cSa = SKAction.playSoundFileNamed("coin4", waitForCompletion: false)
let jA = SKAction.playSoundFileNamed("jump", waitForCompletion: false)
let tTa = SKAction.playSoundFileNamed("tickTock", waitForCompletion: false)
let nA = SKAction.playSoundFileNamed("nitro", waitForCompletion: false)
let dA = SKAction.playSoundFileNamed("player_die", waitForCompletion: false)

override func didMoveToView(view: SKView) {
    physicsWorld.contactDelegate = self
    physicsWorld.gravity = CGVector(dx: 0.0, dy: -20.0)
    setCameraPosition(CGPoint(x: size.width/2, y: size.height/2))
    setupCoreMotion()
    setupNodes()
    setupLevel()
    setupPlayer()
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if !isPlaying {
        bombDrop()
    }
}

override func update(currentTime: NSTimeInterval) {
    // 1
    if lastUpdateTimeInterval > 0 {
        deltaTime = currentTime - lastUpdateTimeInterval
    } else {
        deltaTime = 0
    }
    lastUpdateTimeInterval = currentTime
    // 2
    if paused { return }
    // 3
    if isPlaying == true {
        updateCamera()
        updatePlayer()
        updateLava(deltaTime)
        updateCollisionLava()
    }
    updateLevel()
}

func updateLevel() {
    let cameraPos = getCameraPosition()
    if cameraPos.y > levelY - (size.height * 0.55){
        createBackgroundNode()
        while l {
            <#code#>
        }
        addRandomOverlayNode()
    }
}
func updatePlayer() {
    player.physicsBody?.velocity.dx = xAcceleration * 4000.0

    var playerPosition = convertPoint(player.position,
                                      fromNode: fgNode)
    if playerPosition.x < -player.size.width/2 {
        playerPosition = convertPoint(CGPoint(x: size.width +
            player.size.width/2, y: 0.0), toNode: fgNode)
        player.position.x = playerPosition.x
    }
    else if playerPosition.x > size.width + player.size.width/2 {
        playerPosition = convertPoint(CGPoint(x:
            -player.size.width/2, y: 0.0), toNode: fgNode)
        player.position.x = playerPosition.x
    }
}
func updateCamera() {
    let cameraTarget = convertPoint(player.position, fromNode: fgNode)
    var targetPosition = CGPoint(x: getCameraPosition().x, y: cameraTarget.y - (scene!.view!.bounds.height * 0.40))
    let lavaPos = convertPoint(lava.position, fromNode: fgNode)
    targetPosition.y = max(targetPosition.y, lavaPos.y)
    let diff = targetPosition - getCameraPosition()
    let lerpDiff = diff * lerpValue
    let newPosition = getCameraPosition() + lerpDiff
    setCameraPosition(CGPoint(x: size.width/2, y: newPosition.y))
}
func updateLava(dt: NSTimeInterval) {
    let lowerLeft = CGPoint(x: 0, y: cameraNode.position.y - (size.height / 2))
    let visibleMinYFg = scene!.convertPoint(lowerLeft, toNode:
        fgNode).y
    let lavaVelocity = CGPoint(x: 0, y: 120)
    let lavaStep = lavaVelocity * CGFloat(dt)
    var newPosition = lava.position + lavaStep
    newPosition.y = max(newPosition.y, (visibleMinYFg - 125.0))
    lava.position = newPosition
}

func updateCollisionLava() {
    if player.position.y < lava.position.y + 90 {
        boostPlayer()
    }
}

func setupNodes() {
    let worldNode = childNodeWithName("World")!
    bgNode = worldNode.childNodeWithName("Background")!
    background = bgNode.childNodeWithName("Overlay")!.copy() as! SKNode
    backHeight = background.calculateAccumulatedFrame().height
    fgNode = worldNode.childNodeWithName("Foreground")!
    player = fgNode.childNodeWithName("Player") as! SKSpriteNode
    lava = fgNode.childNodeWithName("Lava") as! SKSpriteNode
    fgNode.childNodeWithName("Bomb")?.runAction(SKAction.hide())

    platformArrow = loadOverlayNode("PlatformArrow")//
    platform5Across = loadOverlayNode("Platform5Across")//
    platformDiagonal = loadOverlayNode("PlatformDiagonal")//
    breakArrow = loadOverlayNode("BreakArrow") //
    break5Across = loadOverlayNode("Break5Across") // -> //
    breakDiagonal = loadOverlayNode("BreakDiagonal")//
    coin5Across = loadOverlayNode("Coin5Across")//
    coinDiagonal = loadOverlayNode("CoinDiagonal")//
    coinCross = loadOverlayNode("CoinCross")//
    coinArrow = loadOverlayNode("CoinArrow")//
    coinS5Across = loadOverlayNode("CoinS5Across")//
    coinSDiagonal = loadOverlayNode("CoinSDiagonal")//
    coinSCross = loadOverlayNode("CoinSCross")//
    coinSArrow = loadOverlayNode("CoinSArrow")//
    platformMove = loadOverlayNode("PlatformMove")//
    enemyPlatform = loadOverlayNode("EnemyPlatform")

    addChild(cameraNode)
    camera = cameraNode
}

func setupLevel() {
    // Place initial platform
    let initialPlatform = platform5Across.copy() as! SKSpriteNode
    var itemPosition = player.position
    itemPosition.y = player.position.y - ((player.size.height * 0.5) + (initialPlatform.size.height * 0.20))
    initialPlatform.position = itemPosition
    fgNode.addChild(initialPlatform)
    lastItemPosition = itemPosition
    lastItemHeight = initialPlatform.size.height / 2.0

    // Create random level
    levelY = bgNode.childNodeWithName("Overlay")!.position.y + backHeight
    while lastItemPosition.y < levelY {
        addRandomOverlayNode()
    }
}

func setupPlayer() {
    player.physicsBody = SKPhysicsBody(texture: player.texture!, size: player.size)
    player.physicsBody!.dynamic = false
    player.physicsBody!.allowsRotation = false
    player.physicsBody!.categoryBitMask = PhysicsCategory.Player
    player.physicsBody!.collisionBitMask = 0
}

func setupCoreMotion() {
    motionManager.accelerometerUpdateInterval = 0.1
    let queue = NSOperationQueue()
    motionManager.startAccelerometerUpdatesToQueue(queue, withHandler: {
    accelerometerData, error in
        guard let accelerometerData = accelerometerData else {
            return
        }
        let acceleration = accelerometerData.acceleration
        self.xAcceleration = (CGFloat(acceleration.x) * 0.75) + (self.xAcceleration * 0.25)
    })
}

func loadOverlayNode(fileName: String) -> SKSpriteNode {
    let overlayScene = SKScene(fileNamed: fileName)!
    let contentTemplateNode =
        overlayScene.childNodeWithName("Overlay")
    return contentTemplateNode as! SKSpriteNode
}
//////////// Here is the problem ///////////
////////////         \/         ///////////
////////////         \/        ///////////
func createOverlayNode(nodeType: SKSpriteNode, flipX: Bool) {
/*here*/let newTile = nodeType.copy() as! SKSpriteNode/*here*/
    lastItemPosition.y = lastItemPosition.y + (lastItemHeight + (newTile.size.height / 2.0))
    lastItemHeight = newTile.size.height / 2.0
    newTile.position = lastItemPosition
    if flipX {
        newTile.xScale = -1.0
    }
    fgNode.addChild(newTile)
}

func createBackgroundNode() {
    let backNode = background.copy() as! SKNode
    backNode.position = CGPoint(x: 0.0, y: levelY)
    bgNode.addChild(backNode)
    levelY += backHeight
}

func addRandomOverlayNode() {
    let overlaySprite: SKSpriteNode!
    var flipH = false
    let platformPercentage = 60

    if Int.random(min: 1, max: 100) <= platformPercentage {
        if Int.random(min: 1, max: 100) <= 75 {
            // Create standard platforms 75%
            switch Int.random(min: 0, max: 3) {
            case 0:
                overlaySprite = enemyPlatform//platformArrow
            case 1:
                overlaySprite = platform5Across
            case 2:
                overlaySprite = platformDiagonal
            case 3:
                overlaySprite = platformDiagonal
                flipH = true
            default:
                overlaySprite = platformArrow
            }
        } else {
            // Create breakable platforms 25%
            switch Int.random(min: 0, max: 5) {
            case 0:
                overlaySprite = breakArrow
            case 1:
                overlaySprite = break5Across
            case 2:
                overlaySprite = breakDiagonal
            case 3:
                overlaySprite = breakDiagonal
                flipH = true
            case 4:
                overlaySprite = platformMove
            case 5:
                overlaySprite = enemyPlatform
            default:
                overlaySprite = breakArrow
            }
        }
    } else {
        if Int.random(min: 1, max: 100) <= 75 {
            // Create standard coins 75%
            switch Int.random(min: 0, max: 4) {
            case 0:
                overlaySprite = coinArrow
            case 1:
                overlaySprite = coin5Across
            case 2:
                overlaySprite = coinDiagonal
            case 3:
                overlaySprite = coinDiagonal
                flipH = true
            case 4:
                overlaySprite = coinCross
            default:
                overlaySprite = coinArrow
            }
        } else {
            // Create special coins 25%
            switch Int.random(min: 0, max: 4) {
            case 0:
                overlaySprite = coinSArrow
            case 1:
                overlaySprite = coinS5Across
            case 2:
                overlaySprite = coinSDiagonal
            case 3:
                overlaySprite = coinSDiagonal
                flipH = true
            case 4:
                overlaySprite = coinSCross
            default:
                overlaySprite = coinSArrow
            }
        }
    }
    createOverlayNode(overlaySprite, flipX: flipH)
}


func bombDrop() {
    isPlaying = true
    let bomb = fgNode.childNodeWithName("Bomb")!
    let scaleUp = SKAction.scaleTo(1.25, duration: 0.25)
    let scaleDown = SKAction.scaleTo(1.0, duration: 0.25)
    let sequence = SKAction.sequence([scaleUp, scaleDown])
    let repeatSeq = SKAction.repeatActionForever(sequence)
    let stop = SKAction.runBlock({self.removeActionForKey("bombing")})
    bomb.runAction(repeatSeq)
    bomb.runAction(SKAction.unhide())
    runAction(tTa, withKey: "bombing")
    runAction(SKAction.sequence([SKAction.waitForDuration(1.0), stop, SKAction.runBlock(startGame)]))
}

func startGame() {
    fgNode.childNodeWithName("Bomb")!.removeFromParent()
    fgNode.childNodeWithName("Title")!.removeFromParent()
    player.physicsBody!.dynamic = true
    superBoostPlayer()
}

func setPlayerVelocity(amount:CGFloat) {
    let gain: CGFloat = 2.5
    player.physicsBody!.velocity.dy = max(player.physicsBody!.velocity.dy, amount * gain)
}

func jumpPlayer() {
    setPlayerVelocity(800)
    runAction(jA)
}
func boostPlayer() {
    setPlayerVelocity(1400)
}
func superBoostPlayer() {
    setPlayerVelocity(2000)
    runAction(nA)
}

func didBeginContact(contact: SKPhysicsContact) {
    let other = contact.bodyA.categoryBitMask ==
        PhysicsCategory.Player ? contact.bodyB : contact.bodyA
    switch other.categoryBitMask {
    case PhysicsCategory.CoinNormal:
        if let coin = other.node as? SKSpriteNode {
            jumpPlayer()
            explode(coin, category: "CollectNormal")
            runAction(cNa)
        }
    case PhysicsCategory.PlatformNormal:
        if let platform = other.node as? SKSpriteNode {
            if player.physicsBody!.velocity.dy < 0 {
                jumpPlayer()
                wiggle(platform)
            }
        }
    case PhysicsCategory.PlatformBreakable:
        if let platform = other.node as? SKSpriteNode {
            if player.physicsBody!.velocity.dy < 0 {
                jumpPlayer()
                explode(platform, category: "BrokenPlatform")
            }
        }
    case PhysicsCategory.CoinSpecial:
        if let coin = other.node as? SKSpriteNode {
            boostPlayer()
            explode(coin, category: "CollectSpecial")
            runAction(cSa)
        }
    case PhysicsCategory.PlatformDead:
        if let platform = other.node as? SKSpriteNode {
            let velocityY = player.physicsBody!.velocity.dy
            if velocityY < 0 {
                explode(platform, category: "BrokenPlatform")
                jumpPlayer()
                wiggle(platform)
            } else if velocityY > 0 {
                explode(platform, category: "BloodingPlatform")
                runAction(dA)
            }
        }
    default:
        break;
    }
}

func overlapAmount() -> CGFloat {
    guard let view = self.view else {
        return 0 }
    let scale = view.bounds.size.height / self.size.height
    let scaledWidth = self.size.width * scale
    let scaledOverlap = scaledWidth - view.bounds.size.width
    return scaledOverlap / scale
}

func getCameraPosition() -> CGPoint {
    return CGPoint(
        x: cameraNode.position.x + overlapAmount()/2,
        y: cameraNode.position.y)
}

func setCameraPosition(position: CGPoint) {
    cameraNode.position = CGPoint(
        x: position.x - overlapAmount()/2,
        y: position.y)
}

func explode(node: SKSpriteNode, category: String) {
    node.removeAllActions()
    node.texture = nil
    node.physicsBody = nil
    let effect = SKEmitterNode(fileNamed: category)!
    node.addChild(effect)
    node.runAction(SKAction.sequence([SKAction.waitForDuration(1.0), SKAction.removeFromParent()]))
}

func wiggle(object: SKSpriteNode) {
    let posY = object.position.y
    let wiggle = SKAction.sequence([SKAction.moveToY(posY-50, duration: 0.1), SKAction.moveToY(posY, duration: 0.1), SKAction.moveToY(posY-10, duration: 0.05), SKAction.moveToY(posY, duration: 0.025),SKAction.moveToY(posY-5, duration: 0.01), SKAction.moveToY(posY, duration: 0.01)])
    object.runAction(wiggle)
}
}

出现错误的行:

    func createOverlayNode(nodeType: SKSpriteNode, flipX: Bool) {
        let newTile = nodeType.copy() as! SKSpriteNode
        lastItemPosition.y = lastItemPosition.y + (lastItemHeight + (newTile.size.height / 2.0))
        lastItemHeight = newTile.size.height / 2.0
        newTile.position = lastItemPosition
        if flipX {
            newTile.xScale = -1.0
        }
        fgNode.addChild(newTile)
    }

这是崩溃报告:

    Thread 0 name:  Dispatch queue: com.apple.main-thread
    Thread 0 Crashed:
    0   libc++abi.dylib                 0x0000000181e3cce4 __dynamic_cast + 52
    1   SpriteKit                       0x000000019072a098 __15-[SKNode scene]_block_invoke + 60
    2   SpriteKit                       0x000000019072a098 __15-[SKNode scene]_block_invoke + 60
    3   SpriteKit                       0x00000001906ec7e8 SKCNode::walkUp(void (SKCNode*, bool*) block_pointer, bool) + 76
    4   SpriteKit                       0x0000000190729fec -[SKNode scene] + 132
    5   SpriteKit                       0x000000019072adc8 -[SKNode removeChild:] + 76
    6   SpriteKit                       0x0000000190729d90 -[SKNode removeFromParent] + 168
    7   SpriteKit                       0x00000001906e8ddc -[SKReferenceNode copyWithZone:] + 56
    8   CoreFoundation                  0x00000001826c6b38 -[NSArray initWithArray:range:copyItems:] + 288
    9   SpriteKit                       0x00000001907293f8 -[SKNode copyWithZone:] + 896
    10  SpriteKit                       0x0000000190738bfc -[SKSpriteNode  copyWithZone:] + 56

我已经尝试修复此错误2天但没有任何改变,所以我会对有用的答案感到高兴。

1 个答案:

答案 0 :(得分:0)

更改此行:

 let newTile = nodeType.copy() as! SKSpriteNode

使用:

let newTile = nodeType

关于您的问题:

@available(iOS 2.0, *)
public class NSObject : NSObjectProtocol {
    public func copy() -> AnyObject
}

您尝试使用尚未存在的初始化对象的复制方法,因此编译器会出错。