在SpriteKit播放声音时,它会加速计

时间:2016-12-19 14:43:27

标签: 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分,它可能很快甚至更晚都没有一致性。

非常感谢任何意见,谢谢你提前

1 个答案:

答案 0 :(得分:0)

看看这个更新的场景,一些主要的变化是我将你的3个单独的块组合成1个SKNode,这样我只需要移动单个SKNode,然后我将它设置为你在结束时得分的位置联系,而不是开始。您还可以看到滚动完成时块现在已经死亡,滚动后背景效率更高。如果您对更改有任何其他问题,请随时提出。

//
//  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:()

        }

    }

}