无法理解我的spritekit游戏中的滞后?

时间:2017-03-27 18:16:31

标签: ios swift sprite-kit avfoundation lag

制作一个简单的spritekit游戏。在AVFoundation声音库中,我有按钮触摸声音等声音。但是这有麻烦。当听到任何按钮时,我的帧速率总是会下降。但如果我把所有的声音静音,就没有滞后。这是我的代码:

import AVFoundation

class GameAudio {
    static let shared = GameAudio()

    private var buttonClickSound = AVAudioPlayer()
    private var completionSound = AVAudioPlayer()
    private var swishSound = AVAudioPlayer()
    private var gridSwishSound = AVAudioPlayer()
    private let Volume: Float = 0.8

    func setupSounds() {
        print("GameAudio setupSounds()")
        if let path = Bundle.main.path(forResource: SoundNames.ButtonClickSoundName, ofType: "mp3") {
            let url = URL(fileURLWithPath: path )
            do {
                buttonClickSound = try AVAudioPlayer(contentsOf: url)
            } catch {
                print(error)
            }
        }
        if let path = Bundle.main.path(forResource: SoundNames.CompletionSoundName, ofType: "mp3") {
            let url = URL(fileURLWithPath: path)
            do {
                completionSound = try AVAudioPlayer(contentsOf: url)
            } catch {
                print(error)
            }
        }
        if let path = Bundle.main.path(forResource: SoundNames.SwishSoundName, ofType: "mp3") {
            let url = URL(fileURLWithPath: path )
            do {
                swishSound = try AVAudioPlayer(contentsOf: url)
            } catch {
                print(error)
            }
        }
        if let path = Bundle.main.path(forResource: SoundNames.GridSwishSoundName, ofType: "mp3") {
            let url = URL(fileURLWithPath: path)
            do {
                gridSwishSound = try AVAudioPlayer(contentsOf: url)
            } catch {
                print(error)
            }
        }
        buttonClickSound.volume = Volume
        completionSound.volume = Volume
        swishSound.volume = Volume
        gridSwishSound.volume = Volume
    }

    func playButtonClickSound() {
        buttonClickSound.play()
    }

    func playCompletionSound() {
        completionSound.play()
    }

    func playSwishSound() {
        swishSound.play()
    }

    func playGridSwishSound() {
        gridSwishSound.play()
    }
}

在我的GameViewController中,我调用GameAudio.shared.setupSounds()来预加载所有声音。

public struct Actions {
    static func buttonIsTouched(_ button: SKNode, sound: Bool, completion: @escaping () -> ()) {
        if button.hasActions() { return }
        if sound {
            GameAudio.shared.playButtonClickSound()
        }
        button.run(touchedButtonAction(scaleFactor: button.returnScaleFactor()), completion: completion)
    }
}

class MenuNode: SKNode {
    private let settings: Settings

    var delegate: MenuNodeDelegate?

    private let playButton = SKSpriteNode(imageNamed: SpriteNames.PlayButtonName)

    private let MenuNodeTreshold: CGFloat = 12.0

    init(settings: Settings) {
        self.settings = settings
        super.init()

        setupButtons()

        isUserInteractionEnabled = false
    }

    private func setupButtons() {
        playButton.position = CGPoint(x: 0.0 - playButton.frame.size.width / 2.0 - MenuNodeTreshold / 2.0, y: 0.0)
        addChild(playButton)
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in: self)

            if playButton.contains(location) {
                Actions.buttonIsTouched(playButton as SKNode, sound: settings.sound, completion: {
                    self.delegate?.playButtonTouched()
                })
            }
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

我在游戏中使用Actions结构进行所有操作。我有buttonTouchedAction(),我在不同的节点中使用它。我用一个“播放”按钮从菜单中输入了一些代码。因此,例如,我在设备上运行我的游戏,它显示菜单节点,等待几秒钟并点击按钮,在我的帧速率下降之后,我有一秒钟的滞后然后场景变为游戏场景。

2 个答案:

答案 0 :(得分:1)

我有类似的问题。我最后使用role播放短音。

    h1,w1 = imageB.shape[:2]
    h2,w2 = imageA.shape[:2]
    pts1 = np.float32([[0,0],[0,h1],[w1,h1],[w1,0]]).reshape(-1,1,2)
    pts2 = np.float32([[0,0],[0,h2],[w2,h2],[w2,0]]).reshape(-1,1,2)
    pts2_ = cv2.perspectiveTransform(pts2, H)
    pts = np.concatenate((pts1, pts2_), axis=0)
    # print("pts:", pts)
    [xmin, ymin] = np.int32(pts.min(axis=0).ravel() - 0.5)
    [xmax, ymax] = np.int32(pts.max(axis=0).ravel() + 0.5)
    t = [-xmin,-ymin]
    Ht = np.array([[1,0,t[0]],[0,1,t[1]],[0,0,1]]) # translate

    result = cv2.warpPerspective(imageA, Ht.dot(H), (xmax-xmin, ymax-ymin))

    resizedB = np.zeros((result.shape[0], result.shape[1], 3), np.uint8)

    resizedB[t[1]:t[1]+h1,t[0]:w1+t[0]] = imageB
    # Now create a mask of logo and create its inverse mask also
    img2gray = cv2.cvtColor(result,cv2.COLOR_BGR2GRAY)
    ret, mask = cv2.threshold(img2gray, 0, 255, cv2.THRESH_BINARY)

    kernel = np.ones((5,5),np.uint8)
    k1 = (kernel == 1).astype('uint8')
    mask = cv2.erode(mask, k1, borderType=cv2.BORDER_CONSTANT)

    mask_inv = cv2.bitwise_not(mask)

    difference = cv2.bitwise_or(resizedB, resizedB, mask=mask_inv)

    result2 = cv2.bitwise_and(result, result, mask=mask)

    result = cv2.add(result2, difference)

有关详细信息,请参阅SKAction reference

答案 1 :(得分:1)

如果你想使用AVAudioPlayer(而不是SpriteKit's声音动作),你应该让声音在后台线程中播放,这样它的操作就不会干扰主线程你所有的视觉内容都是:

 let soundQueue = OperationQueue()
 soundQueue.qualityOfService = QualityOfService.background 
 soundQueue.addOperation{self.buttonClickSound.play()}