当敌人产卵时,应用会冻结

时间:2016-07-13 17:36:19

标签: ios swift sprite-kit

当我运行我的应用程序时,似乎当游戏在spawnEnemies()中生成敌人时,在添加敌人孩子的while循环期间,整个应用程序冻结。没有SKActions运行且没有注册触摸输入。是什么导致了这个问题?感谢

//
//  GameScene.swift
//  Defence
//
//  Created by iD Student on 7/6/16.
//  Copyright (c) 2016 iD Tech. All rights reserved.
//

import SpriteKit

struct DefType {
    static let basic: Int = 1

}

struct EnemyType {
    static let basic: Int = 1
}

class GameScene: SKScene, SKPhysicsContactDelegate {

    var basicDef = SKSpriteNode()

    var defencesArr: [Defence] = []
    var enemiesArr: [Enemy] = []

    var waveCount: Double = 0

    //Interval between which enemies are spawned
    var spawnRate:Double  = 2

    //Percentage increase per level of spawnRate
    var spawnRateScale: Double = 0.05

    var timeOfLastSpawn: Double = 0

    var basicEnemySpawnBase: Double = 5
    var basicEnemySpawnScale: Double = 0.5
    var basicEnemySpawned: Int = 0

    //Time between each wave
    var waveTimer: Double = 0

    var timeOfLastWave: Double = 0

    var touchLocation = CGPointZero
    var placementPos = CGPointZero

    var basicDefSelected: Bool = false
    let basicDefSelector = SKSpriteNode()

    var selectedNode = SKSpriteNode()

    override func didMoveToView(view: SKView) {
        backgroundColor = UIColor.blackColor()

        basicDef.texture = SKTexture(imageNamed: "basic.png")
        basicDef.size = CGSize(width: 40, height: 40)
        basicDef.position = CGPoint(x: size.width-20, y: 30)

        self.addChild(basicDef)

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("tapped:"))
        let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: Selector("pressed:"))
        let gestureRecognizer = UIPanGestureRecognizer(target: self, action: Selector("handlePanFrom:"))

        view.addGestureRecognizer(gestureRecognizer)
        view.addGestureRecognizer(tapGestureRecognizer)
        view.addGestureRecognizer(longPressRecognizer)

        physicsWorld.gravity = CGVectorMake(0, 0)
        physicsWorld.contactDelegate = self
    }

    func tapped(sender: UITapGestureRecognizer) {

    }

    func pressed(sender: UILongPressGestureRecognizer) {

    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    }

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    }

    func addDefence(type: Int) {
        var defenceAdded: Defence = Defence(type: DefType.basic)

        switch type {
        case DefType.basic:
            defenceAdded = Defence(type: DefType.basic)
            break

        default:
            break
        }

        defencesArr.append(defenceAdded)
        addChild(defenceAdded)
        defenceAdded.position = placementPos

    }

    func selectNodeForTouch(touchLocation : CGPoint) {

        let touchedNode = self.nodeAtPoint(touchLocation)

        if touchedNode is SKSpriteNode && touchedNode.physicsBody?.categoryBitMask != 0 && selectedNode.physicsBody?.categoryBitMask != 0{

            if !selectedNode.isEqual(touchedNode){
                selectedNode.removeAllActions()
                selectedNode = touchedNode as! SKSpriteNode

            }
        }
    }

    func handlePanFrom(recognizer : UIPanGestureRecognizer) {
        if recognizer.state == .Began {
            touchLocation = recognizer.locationInView(recognizer.view)
            touchLocation = convertPointFromView(touchLocation)

            selectNodeForTouch(touchLocation)

            if basicDef == selectedNode{
                basicDefSelector.size = CGSize(width: 40, height: 40)
                basicDefSelector.alpha = 0.5
                basicDefSelector.position = touchLocation
                basicDefSelector.texture = SKTexture(imageNamed: "basic.png")
                addChild(basicDefSelector)

                selectedNode = basicDefSelector
                basicDefSelected = true
            }

        } else if recognizer.state == .Changed {
            var translation = recognizer.translationInView(recognizer.view!)
            translation = CGPoint(x: translation.x, y: -translation.y)

            selectedNode.position = CGPoint(x: selectedNode.position.x + translation.x, y: selectedNode.position.y + translation.y)
            recognizer.setTranslation(CGPointZero, inView: recognizer.view)

        } else if recognizer.state == .Ended {
            if basicDefSelected == true {
                placementPos = selectedNode.position
                basicDefSelector.removeFromParent()
                addDefence(DefType.basic)
                basicDefSelected = false
            }

            selectedNode = SKSpriteNode()
        }
    }

    func spawnEnemies(wave: Double) {
        var enemiesToBeAdded: [Int] = []
        var enemyToBeAdded: Int = EnemyType.basic
        var enemyAdded: Enemy = Enemy(type: EnemyType.basic)

        var basicEnemySpawnAmount = basicEnemySpawnBase + (wave * basicEnemySpawnScale)

        while basicEnemySpawnAmount > 0 {
            print(basicEnemySpawnAmount)
            enemyToBeAdded = EnemyType.basic
            enemiesToBeAdded.append(enemyToBeAdded)
            basicEnemySpawnAmount -= 1
        }

        while enemiesToBeAdded.count > 0 {
            print("TimeDifferential \(CACurrentMediaTime() - timeOfLastSpawn)")
            if (CACurrentMediaTime() - timeOfLastSpawn) >= spawnRate {
                print("spawned")
                let randomX = drand48() * Double(size.width-80)

                let enemyPos: CGPoint = CGPoint(x: CGFloat(randomX), y: size.height+100)
                let randomIndex = arc4random_uniform(UInt32(enemiesToBeAdded.count))

                switch enemiesToBeAdded[Int(randomIndex)] {
                case EnemyType.basic:
                    enemyAdded = Enemy(type: EnemyType.basic)
                    break

                default:
                    break
                }

                addChild(enemyAdded)
                enemyAdded.position = enemyPos
                enemiesArr.append(enemyAdded)
                enemiesToBeAdded.removeAtIndex(Int(randomIndex))

                var movEnemy: SKAction
                movEnemy = SKAction.moveTo(CGPoint(x: enemyAdded.position.x, y: -100), duration: enemyAdded.flightSpeed)
                enemyAdded.runAction(SKAction.sequence([movEnemy, SKAction.removeFromParent()]))


                timeOfLastSpawn = CACurrentMediaTime()
            }
        }

    }

    override func update(currentTime: CFTimeInterval) {
        waveTimer = (waveCount * spawnRate * (1+spawnRateScale)) + 20

        for defence in defencesArr {
            if defence.towerType == DefType.basic {
                if (CACurrentMediaTime() - defence.lastShotTime) >= defence.fireRate {
                    let bullet = SKSpriteNode()

                    bullet.texture = SKTexture(imageNamed: "basicBullet.png")
                    bullet.size = CGSize(width: 40, height: 40)
                    bullet.position = CGPoint(x: defence.position.x, y: defence.position.y+20)

                    addChild(bullet)
                    let vector = CGVectorMake(0, CGFloat(defence.bulletRange))
                    let projectileAction = SKAction.sequence([
                        SKAction.moveBy(vector, duration: defence.bulletSpeed),
                        SKAction.removeFromParent()
                        ])

                    bullet.runAction(projectileAction)

                    defence.lastShotTime = CACurrentMediaTime()
                }
            }
        }

        if (CACurrentMediaTime() - timeOfLastWave) >= waveTimer {
            timeOfLastWave = CACurrentMediaTime()
            spawnEnemies(waveCount)
            waveCount += 1
        }
    }
}

1 个答案:

答案 0 :(得分:1)

你的应用程序因为过度循环而冻结。当我运行你的代码时,在第1级,我计算了循环次数。

第一次通过:

Total loops: 192078

第二次通过:

Total loops: 339925

因此,对于wave 1,您正在主线程上运行超过192,000个循环。这肯定会冻结你的应用程序。