swift - 碰撞后转换自定义 SKSpriteNode 类

标签 swift xcode sprite-kit xcode8-beta2

我有几个从 SKSpriteNode 派生的自定义类,当它们发生冲突时,我想从自定义“Treat”类中调用一个方法,但它因错误而崩溃。”展开 optional 时意外发现 Nil值”

这是Treat类...

import UIKit
import SpriteKit

class Treat: SKSpriteNode {

var isActive: Bool!

override init(texture: SKTexture!, color: SKColor, size: CGSize) {
    self.isActive = true

    super.init(texture: texture, color: color, size: size)

    self.texture = SKTexture(imageNamed: "treat1")
    self.zPosition = 3
    self.size = CGSize(width: 25, height: 25)
    self.physicsBody = SKPhysicsBody(rectangleOf: self.size)

    self.physicsBody?.friction = 0.1
    self.physicsBody?.restitution = 0.8
    self.physicsBody?.mass = 0.01
    self.physicsBody?.affectedByGravity = true
    self.physicsBody?.allowsRotation = true
    self.physicsBody?.isDynamic = true
    self.physicsBody?.categoryBitMask = PhysicsCategory.Treat
    self.physicsBody?.contactTestBitMask = PhysicsCategory.Player
    self.physicsBody?.collisionBitMask = PhysicsCategory.Ground
    self.physicsBody?.usesPreciseCollisionDetection = true
    self.name = "Treat";

    let rotateDuration = Double(arc4random()) / 0xFFFFFFFF
    let rotateAction = SKAction.rotate(byAngle: CGFloat(M_PI), duration: rotateDuration)
    let rotateActionRepeatingForever = SKAction.repeatForever(rotateAction)
    self.run(rotateActionRepeatingForever)

}

convenience init(color: SKColor, isActive: Bool = false) {
    let size = CGSize(width:0, height: 0);
    self.init(texture:nil, color: color, size: size)
    self.isActive = isActive
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

func throwTreat() {
    NSLog("Throwing Treat")
    let arc4randoMax:Double = 0x100000000
    let upper = 2.0
    let lower = 4.4
    let throwableAngle = Float32((Double(arc4random()) / arc4randoMax) * (upper - lower) + lower)

    self.physicsBody?.applyImpulse(CGVector(dx: CGFloat(-throwableAngle),dy: CGFloat(throwableAngle)))
}

func removeTreat(showEffect: Bool) {
    if self.isActive != false {
        self.isActive = false
        if showEffect != false {

        }
        self.removeFromParent()
    }

}

func onImpactWithPlayer() {
    self.removeFromParent()
}


}

这就是物理碰撞检测..

 func didBegin(_ contact: SKPhysicsContact) {

    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }

    if ((firstBody.categoryBitMask & PhysicsCategory.Player != 0) &&
        (secondBody.categoryBitMask & PhysicsCategory.Ground != 0)) {
        self.playerNode.isJumping = false
    }


    if ((firstBody.categoryBitMask & PhysicsCategory.Player != 0) &&
        (secondBody.categoryBitMask & PhysicsCategory.Treat != 0)) {
        levelScore = levelScore + 1
        (secondBody.node as! Treat).onImpactWithPlayer() // This line crashes

    }

}

我是快速和面向对象编程的新手,所以目前没有多大意义。我知道这是一个简单的修复,但我很愚蠢......

最佳答案

您的代码看起来大部分是正确的。

我相信这里正在发生的事情

当两个物理体碰撞时,didBegin(_ contact: SKPhysicsContact) 可以是 called several times在同一帧上。

从这里开始

(secondBody.node as! Treat).onImpactWithPlayer()

您正在从场景图中删除 Treat,下次在同一帧上调用 didBegin(_ contact:) 时,您会崩溃,因为该节点已被删除。

解决方案

替换这个即可

(secondBody.node as! Treat).onImpactWithPlayer()

有了这个

 (secondBody.node as? Treat)?.onImpactWithPlayer()

关于swift - 碰撞后转换自定义 SKSpriteNode 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38805734/

相关文章:

ios - 尝试让我的应用播放像 Snapchat Stories 一样的故事

ios - 为 splitViewController displayModeButtonItem (UIBarButtonItem) Swift IOS 9 使用自定义图像时遇到问题

swift - 如何使用 applicationdidBecomeActive 函数呈现 ViewController(但有一些异常(exception))?

ios - 以百分比形式为两个 UIView 指定约束

iphone - 为什么我的 ASIHTTPRequest 文件显示 ARC 错误?

ios - 是否可以将 SKScene 与 UIView Controller 一起使用?

ios - SKAction.repeatActionForever 只在第一次调用时计算随机数

返回 nil 的 swift 函数(返回太早)

ios - 不同设备宽度的 View 大小和对齐方式不同

ios - 重力属性在 SpriteKit 场景中不起作用