Swift Spritekit didBeginContact被延迟调用

时间:2019-02-27 11:54:17

标签: swift sprite-kit skspritenode

这是我的GameScene代码。

class GameScene: SKScene, SKPhysicsContactDelegate {

    let orcWidth = UIScreen.main.bounds.width / 5

    var orcCategory:UInt32 = 0x1 << 0
    var knightCategory:UInt32 = 0x1 << 1

    private var orc = SKSpriteNode()
    private var  knight = SKSpriteNode()
    private var orcWalkingFrames: [SKTexture] = []
    private var knightIdleFrames: [SKTexture] = []
    private var knightAttackFrame: [SKTexture] = []
    var background = SKSpriteNode(imageNamed: "game_background1")

    override func didMove(to view: SKView) {
        physicsWorld.contactDelegate = self
        physicsWorld.gravity = CGVector(dx: 0, dy: 0)
        setupbackground()
        startGame()
    }

    func setupbackground() {
        background.zPosition = 0
        background.size = self.frame.size
        background.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
        addChild(background)
    }

    func startGame() {
        buildRandomOrcs()
        buildKnight()
    }

    func stopGame() {
    }

    func buildOrc(yposition: CGFloat) {
        var orcWalkFrames: [SKTexture] = []
        let orcAnimatedAtlas = SKTextureAtlas(named: "OrcWalking")

        let numImages = orcAnimatedAtlas.textureNames.count
        for i in 0...numImages - 1 {
            let orcTextureName = "0_Orc_Walking_\(i)"
            orcWalkFrames.append(orcAnimatedAtlas.textureNamed(orcTextureName))
        }
        self.orcWalkingFrames = orcWalkFrames

        let firstFrameTexture = orcWalkingFrames[0]
        orc = SKSpriteNode(texture: firstFrameTexture)
        orc.name = "orc"
        orc.position = CGPoint(x: frame.minX-orcWidth/2, y: yposition)
        self.orc.zPosition = CGFloat(self.children.count)
        orc.scale(to: CGSize(width: orcWidth, height: orcWidth))
        orc.physicsBody = SKPhysicsBody(rectangleOf: orc.size, center: orc.position)
        orc.physicsBody?.affectedByGravity = false
        orc.physicsBody?.isDynamic = true
        orc.physicsBody?.categoryBitMask = orcCategory
        orc.physicsBody?.contactTestBitMask = knightCategory
        orc.physicsBody?.collisionBitMask = knightCategory
        addChild(orc)
        walkOrc()
        moveOrcForward()
    }

    func buildKnight() {
        var knightIdleFrames: [SKTexture] = []
        let knightIdleAtlas = SKTextureAtlas(named: "KnightIdle")

        let numImages = knightIdleAtlas.textureNames.count
        for i in 0...numImages - 1 {
            let orcTextureName = "_IDLE_00\(i)"
            knightIdleFrames.append(knightIdleAtlas.textureNamed(orcTextureName))
        }
        self.knightIdleFrames = knightIdleFrames

        let firstFrameTexture = knightIdleFrames[0]
        knight = SKSpriteNode(texture: firstFrameTexture)
        knight.name = "knight"
        knight.position = CGPoint(x: frame.maxX-orcWidth/2, y: frame.midY)
        self.knight.zPosition = 1
        knight.scale(to: CGSize(width: -orcWidth, height: orcWidth))
        knight.physicsBody = SKPhysicsBody(rectangleOf: knight.size, center: knight.position)
        knight.physicsBody?.affectedByGravity = false
        knight.physicsBody?.isDynamic = false
        knight.physicsBody?.categoryBitMask     = knightCategory
        knight.physicsBody?.contactTestBitMask = orcCategory
        knight.physicsBody?.collisionBitMask     = orcCategory
        addChild(knight)
        idleKnight()
    }

    func idleKnight() {
        knight.run(SKAction.repeatForever(SKAction.animate(with: knightIdleFrames, timePerFrame: 0.1)))
    }

    func walkOrc() {
        orc.run(SKAction.repeatForever(SKAction.animate(with: orcWalkingFrames,timePerFrame: 0.025)))
    }

    func moveOrcForward() {
        orc.run(SKAction.repeatForever(SKAction.moveBy(x: 55, y: 0, duration: 0.25)))
    }

    func buildRandomOrcs () {
        let wait = SKAction.wait(forDuration: TimeInterval(makeRandomNumberBetween(min: 0, max: 0)))
        let spawn = SKAction.run {
            self.buildOrc(yposition: self.makeRandomCGFloatNumber())
        }

        let spawning = SKAction.sequence([spawn,wait])

        self.run(SKAction.repeat(spawning, count: 10))
    }

    func makeRandomCGFloatNumber() -> CGFloat {
        let randomNumber = arc4random_uniform(UInt32((frame.maxY-orcWidth/2) - (frame.minY+orcWidth/2))) + UInt32(frame.minY+orcWidth/2)
        return CGFloat(randomNumber)

    }

    func makeRandomNumberBetween (min: Int, max: Int) -> Int{
        let randomNumber = arc4random_uniform(UInt32(max - min)) + UInt32(min)
        return Int(randomNumber)
    }


    func didBegin(_ contact: SKPhysicsContact) {
        let collision:UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
        if collision == orcCategory | knightCategory {
            self.scene?.view?.isPaused = true
            print("COLLIDED")
        }
    }
}

问题在于,碰撞后场景暂停了将近2-3秒。 我更改了{strong>骑士的position,并更改了延迟时间。

例如,如果我将位置设置为frame.minX+orcWidth/2,则不会延迟。

我的代码有什么问题?

2 个答案:

答案 0 :(得分:2)

您的问题不是事情被拖延了,您的问题是您的边界框不在您认为的位置

使用view.showPhysics = true确定您的盒子在哪里

一旦您意识到它们位于错误的位置,请转到此行

knight.physicsBody = SKPhysicsBody(rectangleOf: knight.size, center: knight.position)

并修复它

knight.physicsBody = SKPhysicsBody(rectangleOf: knight.size)

对其余身体都这样做

答案 1 :(得分:0)

我的猜测是SKView属性的操作必须在主线程上进行,即

DispatchQueue.main.async { [unowned self] in
    self.scene?.view?.isPaused = true
    print("COLLIDED")
}