【问题标题】:Incrementing Score in Swift when SpriteNode goes off screen当 SpriteNode 离开屏幕时在 Swift 中增加分数
【发布时间】:2017-05-11 21:19:45
【问题描述】:

我对此进行了很多搜索,但找不到任何可以提供帮助的内容。 我正在使用 Swift 3 在 SpriteKit 中创建游戏。

SpriteNodes 在屏幕右侧生成,并使用 SKActions 移动到屏幕左侧重复此操作。

我需要一种方法,当 SpriteNode 通过我的玩家(在场景中间)时,分数会增加一。

以下块将我的敌人角色从右到左移动。

func createEnemyBird() {
    // Create Enemy Bird 1
    enemyBird1 = EnemyBird(imageNamed: "enemy 1")
    enemyBird1.position.x = self.frame.width + 100
    enemyBird1.position.y = CGFloat.randomBetweenNumbers(firstNum: -(self.frame.size.height / 2.8), secondNum: (self.frame.size.height / 2.4))
    enemyBird1.name = "EnemyBird1"
    enemyBird1.initialise()

    print(enemyBird1.position.y)

    // Add Physics Bodys
    enemyBird1.physicsBody = SKPhysicsBody(circleOfRadius: self.size.height/10)
    enemyBird1.physicsBody?.allowsRotation = false
    enemyBird1.physicsBody?.affectedByGravity = false
    enemyBird1.physicsBody?.isDynamic = false
    // Add Collision Bitmasks
    enemyBird1.physicsBody?.categoryBitMask = ColliderType.Pipes

    // Animate Enemy Bird
    var enemyBirdAnim = [SKTexture]()
    for i in 1..<5 {
        let enemyName = "enemy \(i)"
        enemyBirdAnim.append(SKTexture(imageNamed: enemyName))
    }
    let animateEnemyBird = SKAction.animate(with: enemyBirdAnim, timePerFrame: 0.08, resize: false, restore: true)
    enemyBird1.run(SKAction.repeatForever(animateEnemyBird))

    // Make enemy Bird Move Left
    let destination = self.frame.width * 2;
    let move = SKAction.moveTo(x: -destination, duration: TimeInterval(6));
    let remove = SKAction.removeFromParent();


    // Run Enemy Bird Mobe
    enemyBird1.run(SKAction.sequence([move, remove]), withKey: "Move")



    // Add Children to scene
    self.addChild(enemyBird1)

}

我也有一个函数但是不知道什么时候调用它

    // Score increase
func incrementScore() {
    if enemyBird1.position.x == -(self.frame.size.width/2) {
        score += 1
        scoreLabel.text = String(score)
    }
}

我尝试添加一个 SKAction Run Block 在序列中调用它,但效果不佳,因为在它实际开始计数之前大约经过了 6 个敌方角色(这很奇怪)...

【问题讨论】:

  • 任何代码,只要你尝试过的计分方法和球员位置都可以使用。

标签: ios swift sprite-kit skspritenode


【解决方案1】:

一种解决方案是在SKSceneupdate 方法中添加incrementScore 函数:

override func update(_ currentTime: TimeInterval) {

    if !enemyBird1.isScored {
        if enemyBird1.position.x > -self.frame.size.width / 2 {
            score += 1
            scoreLabel.text = String(score)
            enemyBird1.isScored = true
        }
    }

}

update 方法将触发每一帧并检查小鸟是否已通过屏幕中心。如果有,则将其标记为已得分,因此不再计入。

这将要求您将 isScored 属性添加到您的 EnemyBird 类中。

假设您的EnemyBirdSKSpriteNode,它将如下所示:

class EnemyBird: SKSpriteNode {

    var isScored = false

    // other properties, inits, functions, etc

}

【讨论】:

  • 试一试,对 swift 来说非常新,我如何将 isScored 属性添加到enemyBird 类?
  • 这行得通!但由于某种原因,分数从 2 开始,并且当enemyBird1 正好进入屏幕而不是最左边缘时,分数会发生变化。
  • @LukeTerzich 至于屏幕的中心,是因为您在原始问题中指定了 -(self.frame.size.width/2)`。这需要根据场景的锚点所在的位置进行更改。至于从 2 开始,这取决于将鸟添加到场景的位置和方式。我没有足够的信息来调试它。
  • 原来我调用了 createEnemyBird() 函数两次!你的方法很适合得分,而且效果很好!
【解决方案2】:

您可以考虑在 EnemyBird 中覆盖 position 以在鸟的位置发生变化时调用一个函数。例如,在 EnemyBird 类中,您可以添加如下内容:

 override var position: CGPoint {
    didSet {
        if self.position.x == theParentSceneLeftEdge {
        // call a function to update score
        } 
    }
 }

然后,EnemyBird 还需要知道 theParentSceneLeftEdge 的值,您可以在初始化 EnemyBird 时将其指定为等于场景左边缘的值。

希望这会有所帮助!

【讨论】:

    【解决方案3】:

    您只需使用 SKActions 即可完成所有工作。只需将移动分为两部分:首先移动到得分线,然后移动其余部分。在这之间,更新分数。此代码替换了createEnemyBird() 中的“让敌人的鸟向左移动”和“运行敌人的鸟 Mobe”部分:

    // first action moves to the score line
    let scoreLineDestination = -self.frame.width / 2
    let moveToScoreLine = SKAction.moveTo(x: scoreLineDestination, duration: TimeInterval(3));
    
    // second action calls your incrementScore() method
    let increment = SKAction.run(self.incrementScore)
    
    // third action moves the rest of the way
    let finalDestination = -self.frame.width * 2;
    let moveToFinal = SKAction.moveTo(x: finalDestination, duration: TimeInterval(3));
    
    // finally remove
    let remove = SKAction.removeFromParent();
    
    enemyBird1.run(SKAction.sequence([moveToScoreLine, increment, moveToFinal, remove]), withKey: "Move")
    

    您也可以从incrementScore() 中删除位置检查,因为您知道在一只鸟越过得分线之前它不会被调用:

    func incrementScore() {
        score += 1
        scoreLabel.text = String(score)
    }
    

    这样你就不必担心是哪只鸟在叫它。

    【讨论】:

    • 由于某种原因,当 1 只鸟通过时,分数上升得很快,分数约为 100。
    • @LukeTerzich 当我将代码放入一个新项目时,它按预期工作:每只鸟的分数恰好增加一次。听起来您可能正在从其他地方调用incrementScore(),例如其他答案中提到的update()position() 函数。确保它只被SKAction.run() 调用,其他任何地方都没有。
    • 这正是发生的事情,我的问题的两个答案都有效。 A+罗伯特!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 2012-10-22
    • 2015-12-14
    • 1970-01-01
    相关资源
    最近更新 更多