Swift / SpriteKit:尝试从另一个不起作用的类到达类中的函数/方法

时间:2018-02-16 12:26:44

标签: swift sprite-kit skaction

我的ScoreSystem类中有一个名为addScore的函数。该函数为游戏增加1点,将SKLabelNode更新为当前分数,然后每25分调用函数startNewLevel。

func addScore(scene: SKScene) {
    gameScore += 1
    scoreLabel.text = "\(gameScore)"

    if CGFloat(gameScore).truncatingRemainder(dividingBy: 25) == 0 {
        NotificationCenter.default.post(name: Notification.Name.init("start_new_level"), object: nil)
        GameScreen().displayLevel(scene: scene)
    }
}

每次被射击的鱼雷击中敌人时,都会调用该函数。我现在想要添加一个必须避免流星(SKSpriteNode)的新关卡。我按顺序有几个SKActions来完成这个任务。基本上,SKSpriteNode从屏幕顶部移动,到达屏幕下方并被删除。如果流星到达屏幕的底部意味着玩家已经避开了它。

我正在尝试调用addScore函数,但它不会更新。

这是功能:

let scoreSystem = ScoreSystem()

func spawnMeteor() {

    let randomXStart = CGFloat.random(min: gameArea.minX, max: gameArea.maxX)

    let startPoint = CGPoint(x: randomXStart, y: scene.size.height * 1.2)
    let endPoint = CGPoint(x: randomXStart, y: -scene.size.height * 0.2)


    let meteor = SKSpriteNode(imageNamed: "meteor")
    meteor.name = "Meteor"
    meteor.zPosition = 2
    meteor.position = startPoint

    let moveMeteor = SKAction.move(to: endPoint, duration: 3)
    let deleteEnemy = SKAction.removeFromParent()

    let score = SKAction.run(addToScore)

    let meteorSequence = SKAction.sequence([
        moveMeteor,
        score,
        deleteEnemy])

    scene.addChild(meteor)
    meteor.run(meteorSequence)

}

我尝试过这样的函数addToScore:

func addToScore() {
    scoreSystem.addScore(scene: scene!)
}

还试过这个

func addToScore() {
    NotificationCenter.default.post(name: Notification.Name.init("add_to_score"), object: nil)
}

尝试第二种选择时,我将以下内容添加到GameScene

override func sceneDidLoad() {
    super.sceneDidLoad()
    NotificationCenter.default.addObserver(forName: Notification.Name.init("add_to_score"), object: nil, queue: OperationQueue.main) { [weak self] (notification) in
        self?.scoreSystem.addScore(scene: self!)
    }

}

我从spawnMeteor()函数中删除了几行,这样就不会用不必要的代码行阻塞空格。我还没有弄清楚如何使用SKAction.run()调用该函数。有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:0)

您将大量信息传递给您的功能,可能太多了。

我建议您实施协议或通知来处理您的信息,我个人更喜欢协议,所以我的示例将是协议。

我对你的代码做了一些假设,因为并非所有的代码都出现在你的问题中......

protocol ScoreSystemDelegate: class {
    func displayLevel()
}

class ScoreSystem: SKNode {

    weak var scoreSystemDelegate: ScoreSystemDelegate! 

    //your init func and any other funcs in this class (unknown)

    func addScore(scene: SKScene) {
        gameScore += 1
        scoreLabel.text = "\(gameScore)"

        if CGFloat(gameScore).truncatingRemainder(dividingBy: 25) == 0 {
            NotificationCenter.default.post(name: Notification.Name.init("start_new_level"), object: nil)
            //GameScreen().displayLevel(scene: scene)
            self.scoreSystemDelegate.displayLevel()
        }
   }
}

在您的类中创建scoreSystem(假设为GameScene)......

class GameScene: SKScene, ScoreSystemDelegate {

    let scoreSystem = ScoreSystem()
    //assign GameScene as the delegate of ScoreSystem that way the 2 can communicate
    scoreSystem.scoreSystemDelegate = self

    func displayLevel() {
        //do whatever you do when you display the level
    }
}

现在你的spawn meteor func应该按你编码的方式工作,因为addScore不再需要一个场景属性,这个方法的好处是你可以让任何一个对象成为ScoreSystem的委托,它不一定是场景。 / p>