Свифт спрайтекит начал вызывать контакт с задержкой - PullRequest
0 голосов
/ 27 февраля 2019

Это мой 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 секунды после столкновения.Я изменил position из рыцарь и время задержки изменилось.

Например, если я установил положение на frame.minX+orcWidth/2, задержки не будет.

Что не такс моим кодом?

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Ваша проблема не в том, что вещи откладываются, ваша проблема в том, что ваш ограничивающий прямоугольник находится не там, где вы думаете,

используйте view.showPhysics = true, чтобы определить, где находятся ваши блоки

после того, как выпоймите, что они находятся не в том месте, перейдите к этой строке

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

и исправьте ее

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

Сделайте это для остальных ваших тел

0 голосов
/ 27 февраля 2019

Я предполагаю, что манипуляции со свойствами SKView должны происходить в главном потоке, т.е.

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