当 SpriteNode 离开屏幕时在 Swift 中增加分数

Incrementing Score in Swift when SpriteNode goes off screen

我已经搜索了很多,但找不到任何有用的东西。 我正在使用 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 运行 Block 在序列中调用它,但效果不佳,因为在它实际开始计数之前大约有 6 个敌人角色通过(这很奇怪)...

一个解决方案是在 SKScene:

update 方法中添加 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 class。

假设您的 EnemyBirdSKSpriteNode,它将看起来像这样:

class EnemyBird: SKSpriteNode {

    var isScored = false

    // other properties, inits, functions, etc

}

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

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

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

希望对您有所帮助!

您只需使用 SKActions 即可完成所有操作。只需将移动分为两部分:首先移动到得分线,然后移动其余部分。在此期间,更新分数。此代码替换 createEnemyBird():

中的 "Make enemy Bird Move Left" 和 "Run Enemy Bird 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)
}

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