在Swift中未检测到触摸

时间:2018-08-12 11:28:59

标签: ios swift xcode

我一直在用Swift开发一个简单的游戏,以增加对语言语法和概念的了解。我目前面临的问题是在游戏应用程序中未检测到触摸。该应用程序使用动作作为一种关键方法来启动游戏,但是不幸的是,当我点击屏幕时,SKSpriteNodes并没有从屏幕顶部生成(至少从视觉上看)。我进入了几种打印状态,以查看代码是否已达到某些方法,但看起来问题的原因在touch方法内,因为在touch方法上未执行打印行。有人可以帮助我确定我的错误以及如何防止此错误吗?

出于参考目的,我包括了该类:

import SpriteKit
import GameplayKit
class GameScene: SKScene {
    private var counter: Int = 0
    private var level: Int = 0
    private var debug: SKLabelNode?

    // Here we set initial values of counter and level. Debug label is created here as well.

    override func didMove(to view: SKView) {
        counter = 0
        level = 1
        backgroundColor = SKColor.gray
        debug = SKLabelNode(fontNamed: "ArialMT")
        debug?.fontColor = SKColor.purple
        debug?.fontSize = 30.0
        debug?.position = CGPoint(x: frame.midX, y: frame.midY)
        debug?.text = "Counter : [ \(counter) ], Level [ \(level) ]"
        if let aDebug = debug {
            addChild(aDebug)
        }
        print(action(forKey: "counting") == nil)
    }

    //Method to start a timer. SKAction is used here to track a time passed and to maintain the current level
    func startTimer() {
        print("TIMER STARTED...")
        weak var weakSelf: GameScene? = self
        //make a weak reference to scene to avoid retain cycle
        let block = SKAction.run({
            weakSelf?.counter = (weakSelf?.counter ?? 0) + 1
            //Maintaining level
            if (weakSelf?.counter ?? 0) < 5 {
                //level 1
                weakSelf?.level = 1
            } else if (weakSelf?.counter ?? 0) >= 5 && (weakSelf?.counter ?? 0) < 10 {
                //level 2
                weakSelf?.level = 2
            } else {
                //level 3
                weakSelf?.level = 3
            }
            weakSelf?.debug?.text = "Counter : [ \(Int(weakSelf?.counter ?? 0)) ], Level [ \(Int(weakSelf?.level ?? 0)) ]"
        })
        run(SKAction.repeatForever(SKAction.sequence([SKAction.wait(forDuration: 1), block])), withKey: "counting")
    }

    //Method for stopping the timer and reset everything to the default state.
    func stopTimer() {
         print("TIMER STOPPED.")
        if action(forKey: "counting") != nil {
            removeAction(forKey: "counting")
        }
        counter = Int(0.0)
        level = 1
        debug?.text = "Counter : [ \(counter) ], Level [ \(level) ]"
    }

    //Get current speed based on time passed (based on counter variable)
    func getCurrentSpeed() -> CGFloat {
        if counter < 5 {
            //level 1
            return 1.0
        } else if counter >= 5 && counter < 10 {
            //level 2
            return 2.0
        } else {
            //level 3
            return 3.0
        }
    }

    //Method which stops generating stones, called in touchesBegan

    func stopGeneratingStones() {
         print("STOPPED GENERATING STONES...")
        if action(forKey: "spawning") != nil {
            removeAction(forKey: "spawning")
        }
    }

    func randomFloatBetween(_ smallNumber: CGFloat, and bigNumber: CGFloat) -> CGFloat {
        let diff: CGFloat = bigNumber - smallNumber
        //return (CGFloat(arc4random_uniform(UInt32(CGFloat(RAND_MAX) + 1 / CGFloat(RAND_MAX) * diff )))) + smallNumber
         return CGFloat(arc4random() % (UInt32(RAND_MAX) + 1)) / CGFloat(RAND_MAX) * diff + smallNumber
    }

    //Method for generating stones, you run this method when you want to start spawning nodes (eg. didMoveToView or when some button is clicked)
    func generateStones() {
         print("GENERATING STONES...")
        let delay = SKAction.wait(forDuration: 2, withRange: 0.5)
        //randomizing delay time
        weak var weakSelf: GameScene? = self
        //make a weak reference to scene to avoid retain cycle
        let block = SKAction.run({
            let stone: SKSpriteNode? = weakSelf?.spawnStone(withSpeed: weakSelf?.getCurrentSpeed() ?? 0.0)
            stone?.zPosition = 20
            if let aStone = stone {
                weakSelf?.addChild(aStone)
            }
        })
        run(SKAction.repeatForever(SKAction.sequence([delay, block])), withKey: "spawning")
    }

    //Returns stone with moving action added. Inside, you set standard things, like size, texture, physics body, name and position of a stone

    func spawnStone(withSpeed stoneSpeed: CGFloat) -> SKSpriteNode? {
        print("SPAWNNING STONES...")
        let stoneSize = CGSize(width: 30, height: 30) //size of shape.
        //you can randomize size here
        let stonePosition = CGPoint(x: randomFloatBetween(0.0, and: frame.size.width), y: frame.maxY) //initial position
        //you can randomize position here
        let stone = SKSpriteNode(color: SKColor.green, size: stoneSize) //setting size and color.
        stone.name = "stone" //named shape so we can check collision.
        //this helps if you want to enumerate all stones by name later on in your game
        stone.position = stonePosition //set position.
        let move = SKAction.moveBy(x: 0, y: -200, duration: 3.25)
        //one way to change speed
        move.speed = stoneSpeed
        let moveAndRemove = SKAction.sequence([move, SKAction.removeFromParent()])
        stone.run(moveAndRemove, withKey: "moving")
        //access this key if you want to stop movement
        return stone
    }

    func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        /* Called when a touch begins */
        //just a simple way to start and stop a game
        /**
         TOUCH METHOD NOT WORKING.
        */
        if action(forKey: "counting") == nil {
            print("HERE")
            startTimer()
            generateStones()
        } else {
            print("OR HERE")
            stopTimer()
            stopGeneratingStones()
        }
    }

}

1 个答案:

答案 0 :(得分:0)

经过一些调试,我已将问题解决为我自己的问题。我已经意识到touchesBegan方法不会使用覆盖超级方法,因此应用程序将其误认为是本地方法。要解决此问题,只需添加覆盖将解决问题。

更改此内容:

func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
    /* Called when a touch begins */
    //just a simple way to start and stop a game
    /**
     TOUCH METHOD NOT WORKING.
    */
    if action(forKey: "counting") == nil {
        print("HERE")
        startTimer()
        generateStones()
    } else {
        print("OR HERE")
        stopTimer()
        stopGeneratingStones()
    }
}

对此:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        /* Called when a touch begins */
        //just a simple way to start and stop a game
        /**
         TOUCH METHOD NOT WORKING.
        */
        if action(forKey: "counting") == nil {
            print("HERE")
            startTimer()
            generateStones()
        } else {
            print("OR HERE")
            stopTimer()
            stopGeneratingStones()
        }
    }