如何持续射击

时间:2019-04-16 08:10:37

标签: swift sprite-kit

我正在通过一个小游戏学习Swift和SpriteKit,玩家必须在其中保卫军事基地。但是,玩家必须触摸子弹。 但是我想当他触摸屏幕时,火势持续不断,而不是每次都敲击屏幕一次子弹。 此外,当他停下来触摸屏幕时,炮弹也停了下来。

我的Firebullet功能:

func fireBullet () {
    let bullet = SKSpriteNode(imageNamed: "Bullet")
    bullet.name = "Bullet" //afin de permettre l'arrêt des missiles en cas de gameOver
    bullet.setScale(0.5)
    bullet.position = CGPoint(x: planet.position.x, y: planet.position.y)
    bullet.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    bullet.zPosition = 1
    bullet.physicsBody = SKPhysicsBody(rectangleOf: bullet.size) // changer le rectangle en forme circulaire
    bullet.physicsBody!.affectedByGravity = false
    bullet.physicsBody!.categoryBitMask = physicsCategories.bullet
    bullet.physicsBody!.collisionBitMask = physicsCategories.none
    bullet.physicsBody!.contactTestBitMask = physicsCategories.asteroid
    self.addChild(bullet)
    let moveBullet = SKAction.moveTo(y: self.size.height + bullet.size.height, duration: 1.0)
    let deleteBullet = SKAction.removeFromParent()
    let bulletSequence = SKAction.sequence([bulletSound, moveBullet, deleteBullet])
    bullet.run(bulletSequence)
}

我在TouchesBegan中称它为

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if currentGameState == gameState.preGame {
        gameStart()
    }
   else if currentGameState == gameState.inGame {
        fireBullet()
    }

感谢您的帮助:)

3 个答案:

答案 0 :(得分:0)

您可以使用SKAction在其内部调用fireAction。

func fireBullet() {

    ...

    let moveBullet = SKAction.moveTo(y: self.size.height + bullet.size.height, duration: 1.0)
    let deleteBullet = SKAction.removeFromParent()
    let fireCooldown = SKAction.wait(forDuration: 0.5)
    let bulletSequence = SKAction.sequence([bulletSound, moveBullet, deleteBullet, fireCooldown])
    bullet.run(bulletSequence) {
        if currentGameState == gameState.inGame, isTouchingScreen {
            fireBullet()
        }
        // runs actions, wait for 0.5 seconds and trigger a new fireBullet in completion
    }
}

对于冷却时间调整,您可以更改fireCooldown值,或者如果您不想等待整个操作发生,则可以从序列中删除fireCooldown并在完成时单独触发它。 IsTouchingScreen是一个布尔值,您可以在touchesBegan中将其设置为true,然后在touchesEnded中将其设置为false。

答案 1 :(得分:0)

一种实现方法是在update方法中运行它,检查您选择的等待时间,如果时间和isTouching都满足,则调用火弹。

每1.5秒触发一次这样的事情(未经测试,从内存写入)

var isTouching = false
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    fireBall()
    isTouching = true
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    isTouching = false
    dt = 0
}

var lastUpdateTime: TimeInterval = 0
var dt: TimeInterval = 0

override func update(_ currentTime: TimeInterval) {
    //Update time fraction per frame
    if lastUpdateTime > 0 {
        dt += currentTime - lastUpdateTime
    } else {
        dt = 0
    }
    if dt > 1.5 && isTouching {
        fireBall()
        dt = 0
    }
    lastUpdateTime = currentTime
}

另一个重要的事情是:在不再需要该节点时,可以使用延迟作为序列SKAction的结束(等待x秒),然后再执行SKAction.removeFromParent。< / p>

答案 2 :(得分:0)

要连续触发,您需要做的只是简单地创建一系列动作,这些动作将在您进入触摸开始状态时重复,并在您释放触摸时停止操作

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if currentGameState == gameState.preGame {
        gameStart()
    }
    else if currentGameState == gameState.inGame {

        let fire = SKAction.run{self.fireBullet()}
        let wait = SKAction.wait(forDuration:0.1)  //delay between shots
        let seq = SKAction.sequence([fire,wait])
        let repeat = SKAction.repeatForever(seq)
        planet.run(repeat, withKey:"bullets")
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    if currentGameState == gameState.preGame {

    }
    else if currentGameState == gameState.inGame {
        planet.removeAction(forKey:"bullets")
    }
}

现在,您将需要在取消触摸时处理删除操作。您还需要在多根手指按下屏幕时进行处理,因为您不想在操作发生时重新启动操作。

作为旁注,我建议在应用程序的开头创建大量的项目符号,并不断对其进行回收以避免不断产生新的项目符号。