ios - 在 SpriteKit 中,当播放声音时,它会与加速度计混淆

标签 ios swift sprite-kit

我遇到一个问题,即我在更新函数中使用以下代码根据加速度计数据移动角色,如下所示:

        let currentX = self.player.position.x

        if motionManager.isAccelerometerAvailable == true {

            motionManager.startAccelerometerUpdates(to: OperationQueue.current!, withHandler: {

                data, error in

                self.destX = currentX + CGFloat((data?.acceleration.x)! * 40)

                print(CGFloat((data?.acceleration.x)!))

            })

        }

player.position.x = destX

最初我使用 SKAction.moveTo 移动玩家,但出于测试目的已将其删除。

这工作正常,但问题是,我有一个在不可见物体碰撞时播放的声音,当启用此功能时,它会向加速度计发送所有有趣的声音。它没有特定的模式,但过了一会儿,玩家通常会粘在屏幕的任一侧或只是悬停在中间,并且加速度计不会对移动产生任何影响。

我正在使用

播放声音
let playSound = SKAction.playSoundFileNamed("phaserDown3.mp3", waitForCompletion: false)

在文件顶部,然后在发生碰撞时调用 run。

完整代码在这里http://pastebin.com/f6kWTnr7我在这里制作了一个关于这个问题的小视频https://youtu.be/tcGYyrKE4QY - 正如您将看到的,在这种情况下,当分数约为 15 时,它会向左移动一点,然后恢复正常,然后向右移动。它并不总是在 15 分,可能会更早或更晚,根本没有一致性。

任何意见都将不胜感激,提前谢谢

最佳答案

看看这个更新的场景,一些主要的变化是我将你的 3 个独立的 block 组合成 1 个 SKNode,这样我只需要移动单个 SKNode,并且我将它设置在你在一轮结束时得分的位置接触,并不是开始。您还可以看到,滚动完成后, block 现在会消失,并且背景的滚动效率更高。如果您对这些更改还有任何其他疑问,请随时询问。

//
//  GameScene.swift
//  SpriteKitSimpleGame
//
//  Created by James Leist on 28/11/2016.
//  Copyright © 2016 James Leist. All rights reserved.
//

import SpriteKit
import CoreMotion

var motionManager = CMMotionManager()

enum BodyType:UInt32 {

    case player = 1
    case score = 2
    case dontCollide = 4
    case sides = 8

}

class GameScene: SKScene, SKPhysicsContactDelegate {
    var killNodes = [SKNode]()
    //let player = SKSpriteNode(imageNamed: "Airplane")
    let player = SKSpriteNode(color: .green, size: CGSize(width:32,height:32))

    var bg1:SKSpriteNode!
    var bg2:SKSpriteNode!
    let block = SKNode()
    let blockHeight = 50
    var currentScore = 0
    var scoreLabel:SKLabelNode!
    let playSound = SKAction.playSoundFileNamed("phaserDown3.mp3", waitForCompletion: false)
    let move = SKAction.move(by:CGVector(dx:0,dy:-4 * 60),duration:1) //this means we move 4 every 1/60 of a second


    override func didMove(to view: SKView) {

        physicsWorld.contactDelegate = self
        backgroundColor = SKColor.white
        addScrollingBG()
        createRandomBlock()
        addRandomBlocks1()

        // sideRestraints()

        scoreLabel = SKLabelNode(fontNamed: "Copperplate-Bold")
        scoreLabel.text = String(currentScore)
        scoreLabel.fontSize = 80
        scoreLabel.position = CGPoint(x: frame.size.width - 60, y: frame.size.height - 60)
        scoreLabel.zPosition = 20

        self.addChild(scoreLabel)
        player.name = "Player"
        player.zPosition = 15

        player.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)

        // player.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "Airplane"), size: CGSize(width: player.size.width, height: player.size.height))

        player.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: player.size.width, height: player.size.height))

        player.physicsBody?.affectedByGravity = false
        player.physicsBody!.categoryBitMask = BodyType.player.rawValue
        player.physicsBody!.contactTestBitMask = BodyType.score.rawValue | BodyType.sides.rawValue
        player.physicsBody!.collisionBitMask = 0


        addChild(player)

        startAccelerometer()

    }
    func startAccelerometer()
    {
        if motionManager.isAccelerometerAvailable == true {
            motionManager.startAccelerometerUpdates(to: OperationQueue.current!, withHandler: {
                [weak self]  data, error in

                guard let strongSelf = self else {return}
                var destX = UInt32(strongSelf.player.position.x + CGFloat((data?.acceleration.x)! * 40))
                // Called before each frame is rendered */

                if destX <= 0 {
                    destX = 0
                }
                else if destX >= UInt32(strongSelf.frame.size.width) {
                    destX = UInt32(strongSelf.frame.size.width)
                }

                strongSelf.player.position.x = CGFloat(destX)
                print(CGFloat((data?.acceleration.x)!))
            })

        }
    }
    func addScrollingBG() {

        bg1 = SKSpriteNode(imageNamed: "bgPlayScene")
        bg1 = SKSpriteNode(color:.blue,size:self.size)

        bg1.anchorPoint = CGPoint.zero
        bg1.position = CGPoint(x: 0, y: 0)
        // bg1.size = CGSize(width: frame.size.width, height: frame.size.height)
        bg1.zPosition = 0
        addChild(bg1)

        bg2 = SKSpriteNode(imageNamed: "bgPlayScene")
        bg2 = SKSpriteNode(color:.purple,size:self.size)

        bg2.anchorPoint = CGPoint.zero
        bg2.position = CGPoint(x: 0, y: bg1.size.height)
        // bg2.size = CGSize(width: frame.size.width, height: frame.size.height)
        bg2.zPosition = 0
        self.addChild(bg2)
        setupBackgroundAnimation()


    }

    func setupBackgroundAnimation()
    {
        let reset = SKAction.customAction(withDuration: 1,actionBlock:
            {
                node,time in
                guard let sNode = node as? SKSpriteNode else {return}
                sNode.position = sNode.position.y <= -sNode.size.height ?
                    CGPoint(x: sNode.position.x, y: sNode.position.y + sNode.size.height * 2) : sNode.position
        })

        let scroll = SKAction.repeatForever(SKAction.group([move,reset]))
        bg1.run(scroll)
        bg2.run(scroll)



    }
    func createRandomBlock()
    {
        block.position = CGPoint(x:0,y:size.height + CGFloat(blockHeight))

        //let partialBlock = SKSpriteNode(imageNamed: "block")
        let partialBlock = SKSpriteNode(color:.yellow, size:CGSize(width: 1, height: blockHeight))

        let blockLeft1 = partialBlock.copy() as! SKSpriteNode
        blockLeft1.name = "left"
        blockLeft1.anchorPoint = CGPoint.zero

        blockLeft1.size = CGSize(width: 1, height: blockHeight)
        blockLeft1.zPosition = 5;
        blockLeft1.position = CGPoint.zero
        block.addChild(blockLeft1)

        let leftBody =  SKPhysicsBody(rectangleOf: blockLeft1.size)
        leftBody.affectedByGravity = false
        leftBody.categoryBitMask = BodyType.sides.rawValue
        leftBody.contactTestBitMask = 0
        leftBody.collisionBitMask = 0
        leftBody.isDynamic = false
        blockLeft1.physicsBody = leftBody

        let blockRight1 = partialBlock.copy() as! SKSpriteNode
        blockRight1.color = .green
        blockRight1.anchorPoint = CGPoint.zero
        blockRight1.name = "right"

        blockRight1.size = CGSize(width: 1, height: blockHeight)
        blockRight1.zPosition = 5;
        blockRight1.position = CGPoint(x:size.width,y:0)
        block.addChild(blockRight1)

        let rightBody =  SKPhysicsBody(rectangleOf: blockRight1.size)
        rightBody.affectedByGravity = false
        rightBody.categoryBitMask = BodyType.sides.rawValue
        rightBody.contactTestBitMask = 0
        rightBody.collisionBitMask = 0
        rightBody.isDynamic = false
        blockRight1.physicsBody = rightBody

        let scoreBody = SKPhysicsBody(rectangleOf:CGSize(width:Int(frame.size.width),height:blockHeight))
        scoreBody.affectedByGravity = false
        scoreBody.categoryBitMask = BodyType.score.rawValue
        scoreBody.contactTestBitMask = 0
        scoreBody.collisionBitMask = 0
        scoreBody.isDynamic = false
        block.physicsBody = scoreBody
    }
    func addRandomBlocks1() {

        let randomLeftWidth : UInt32  = arc4random_uniform(UInt32(size.width) - 50)

        let randomRightWidth  : UInt32 = arc4random_uniform((UInt32(size.width) - randomLeftWidth) - 50)

        guard let newBlock = block.copy() as? SKNode else {return} //ifw e do not have a node return
        if let leftBlock = newBlock.childNode(withName:"left") as? SKSpriteNode
        {
            leftBlock.xScale = CGFloat(randomLeftWidth)

        }
        if let rightBlock = newBlock.childNode(withName:"right") as? SKSpriteNode
        {
            rightBlock.xScale = -CGFloat(randomRightWidth)
        }

        let addRandom = SKAction.customAction(withDuration: 0, actionBlock:
            {
                [unowned self] node,time in
                if Int(node.position.y) < -self.blockHeight
                {
                    node.removeFromParent()
                    self.addRandomBlocks1()

                }
        })

        newBlock.run(SKAction.repeatForever(SKAction.group([move,addRandom])))

        addChild(newBlock)

    }


    override func update(_ currentTime: CFTimeInterval) {

    }
    override func didFinishUpdate()
    {
        killNodes.forEach{$0.removeFromParent()}
    }


    func didBegin(_ contact: SKPhysicsContact) {

        //This will organize the bodies so that the lowest category is A
        let bodies = (contact.bodyA.categoryBitMask <= contact.bodyB.categoryBitMask) ? (A:contact.bodyA,B:contact.bodyB) : (A:contact.bodyB,B:contact.bodyA)


        switch (bodies.A.categoryBitMask,bodies.B.categoryBitMask)
        {
            case let (a, b) where ((a & BodyType.player.rawValue) | (b & BodyType.sides.rawValue)) > 0:
                killNodes.append(bodies.A.node!)
                let label = SKLabelNode(text: "Gameover")
                label.position = CGPoint(x:self.size.width/2,y:self.size.height/2)
                addChild(label)
            default:()

        }


    }
    func didEnd(_ contact: SKPhysicsContact) {

        //This will organize the bodies so that the lowest category is A
        let bodies = (contact.bodyA.categoryBitMask <= contact.bodyB.categoryBitMask) ? (A:contact.bodyA,B:contact.bodyB) : (A:contact.bodyB,B:contact.bodyA)


        switch (bodies.A.categoryBitMask,bodies.B.categoryBitMask)
        {
        case let (a, b) where ((a & BodyType.player.rawValue) | (b & BodyType.score.rawValue)) > 0:
            currentScore += 1
            run(playSound, withKey:"phaser")

            scoreLabel.text = String(currentScore)
        default:()

        }

    }

}

关于ios - 在 SpriteKit 中,当播放声音时,它会与加速度计混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41225062/

相关文章:

ios - WebThread JavaScriptCore 崩溃——这个崩溃报告意味着什么

android - 如何为 Android 和 iOS 开发一个具有多个实例的应用程序?

inheritance - 使用 swift 在子类中设置基类 'let' 变量

sprite-kit - 翻转的X缩放破坏了碰撞处理(SpriteKit 7.1)

iphone - 如何在 iphone 录音时设置电平表?

ios - Collection View 单元格显示不显示

ios - '[(UIButton) ]' does not have a member named ' enumerate' 谁能指导我解决这个错误?

ios - 如何在 CAShapeLayer 上快速循环显示颜色?

ios - 在 Swift 中从 App 启动 App Store

ios - SKShapeNode空矩形